package com.mes.schedule.manager;

import java.io.Serializable;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Vector;

import javax.annotation.Resource;

import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jdom2.Document;
import org.jdom2.Element;
import org.jdom2.output.Format;
import org.jdom2.output.XMLOutputter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import com.mes.basicdata.dao.DeptDao;
import com.mes.basicdata.dao.OperationDao;
import com.mes.basicdata.dao.PartDao;
import com.mes.basicdata.dao.RoutingDao;
import com.mes.basicdata.dao.WorkCenterDao;
import com.mes.basicdata.domain.Dept;
import com.mes.basicdata.domain.Operation;
import com.mes.basicdata.domain.Part;
import com.mes.basicdata.domain.Routing;
import com.mes.basicdata.domain.WorkCenter;
import com.mes.basicdata.manager.DeptManager;
import com.mes.basicdata.manager.OperationManager;
import com.mes.basicdata.manager.PartManager;
import com.mes.basicdata.manager.RoutingManager;
import com.mes.common.domain.BasicModel;
import com.mes.common.exception.bo.BaseBusinessException;
import com.mes.common.exception.db.BaseDBException;
import com.mes.common.manager.BasicManager;
import com.mes.common.model.ObjectOperation;
import com.mes.common.spring.SpringUtils;
import com.mes.common.util.IdentityGenerator;
import com.mes.common.util.SysUtil;
import com.mes.schedule.algorithm.LinkLagCal;
import com.mes.schedule.algorithm.PriorityCalc;
import com.mes.schedule.dao.DemandSTaskLinkDao;
import com.mes.schedule.dao.SOperationTaskDao;
import com.mes.schedule.dao.SPartTaskDao;
import com.mes.schedule.dao.STaskDao;
import com.mes.schedule.domain.DemandSTaskLink;
import com.mes.schedule.domain.SOperationLink;
import com.mes.schedule.domain.SOperationTask;
import com.mes.schedule.domain.SPartTask;
import com.mes.schedule.domain.ScheduleEvent;
import com.mes.schedule.domain.ScheduleScheme;
import com.mes.schedule.manager.iface.ISchedulePartTaskManager;
import com.mes.schedule.util.ScheduleUtils;
import com.mes.schedule.util.StringOper;
import com.mes.task.dao.DemandDao;
import com.mes.task.dao.PartTaskDao;
import com.mes.task.domain.Demand;
import com.mes.task.domain.PartTask;
import com.mes.task.manager.PartTaskManager;


@Component("schedulePartTaskManager")
@Transactional
public class SchedulePartTaskManager extends BasicManager implements ISchedulePartTaskManager{
	public final static Log log = LogFactory
			.getLog(SchedulePartTaskManager.class);

	private LinkLagCal linkLagCal;
	@javax.annotation.Resource 
	private STaskDao scheduleTaskDao;
	@javax.annotation.Resource 
	private SPartTaskDao schedulePartTaskDao;
	@javax.annotation.Resource
	private PartTaskDao partTaskDao;
	@javax.annotation.Resource 
	private PartTaskManager partTaskManager;
	@javax.annotation.Resource
	private OperationDao operationDao;
	@javax.annotation.Resource
	private WorkCenterDao workCenterDao;
	@javax.annotation.Resource
	private OperationManager operationManager;
	@javax.annotation.Resource
	public ScheduleOperationTaskManager scheduleOperationTaskManager;
	@javax.annotation.Resource
	private ScheduleLinkManager scheduleLinkManager;
	@javax.annotation.Resource
	private RoutingManager routingManager;
	private PriorityCalc priorityCalc;
	@javax.annotation.Resource
	private PartDao partDao;
	@javax.annotation.Resource
	private PartManager partManager;
	@javax.annotation.Resource
	public ScheduleRoutingManager scheduleRoutingManager;

	@javax.annotation.Resource
	public ScheduleEventManager scheduleEventManager;
	@javax.annotation.Resource
	public ScheduleOperationRecordManager scheduleOperationRecordManager;
	@javax.annotation.Resource
	public SOperationTaskDao scheduleOperationTaskDao;
	@javax.annotation.Resource
	public DeptManager deptManager;
	@javax.annotation.Resource
	private DemandSTaskLinkManager demandSTaskLinkManager;
	@javax.annotation.Resource
	private DemandSTaskLinkDao demandSTaskLinkDao;
	@javax.annotation.Resource
	private DemandDao demandDao;
	@Resource
	private ScheduleSchemeManager scheduleSchemeManager;
	@Resource
	private RoutingDao routingDao;
	@Resource
	private DeptDao deptDao;

	
	/**
	 * @param scheduleTaskDao
	 *            the scheduleTaskDao to set
	 */
	public void setScheduleTaskDao(STaskDao scheduleTaskDao) {
		this.scheduleTaskDao = scheduleTaskDao;
	}


	public List<SPartTask> filterPrecise(Collection<SPartTask> partTaskList,
			Map parameters) {
		List<SPartTask> partTaskListForReturn = new LinkedList<SPartTask>();

		Integer priority = (Integer) parameters.get("priority");

		String model = (String) parameters.get("model");
		String drawingId = (String) parameters.get("drawingId");
		String batchNum = (String) parameters.get("batchNum");
		Integer planGrade = (Integer) parameters.get("planGrade");
		Date lateFinish = (Date) parameters.get("lateFinish");
		Integer isCritical = (Integer) parameters.get("isCritical");
		Integer month = (Integer) parameters.get("month");
		for (SPartTask partTask : partTaskList) {

			if (!StringOper.equalsPrecise(model, partTask.getModel()))
				continue;
			if (!StringOper.equalsPrecise(drawingId, partTask.getDrawingId()))
				continue;
			if (!StringOper.equalsPrecise(batchNum, partTask.getBatchNum()))
				continue;

			if (priority != null && priority > 0) {
				int pp = Integer.parseInt(String
						.valueOf(partTask.getPriority()).substring(0, 1));
				if (!priority.equals(pp))
					continue;
			}
			if (planGrade != null && planGrade > 0) {
				if (!partTask.getPlanGrade().equals(planGrade))
					continue;
			}
			if (isCritical != null) {
				if (!(isCritical).equals(partTask.getIsCritical()))
					// if (!partTask.getIsCritical().equals(isCritical))
					continue;
			}
			if (lateFinish != null
					&& (partTask.getLateFinish() == null || partTask
							.getLateFinish().after(lateFinish)))
				continue;

			// add by hba 用于按期过滤零件任务
			if (month != null && month > 0) {
				Date startTime, endTime;
				Calendar calendar = Calendar.getInstance();
				calendar.add(Calendar.MONTH, month - 1);
				calendar.set(Calendar.DAY_OF_MONTH, 1);
				calendar.set(Calendar.HOUR, 0);
				calendar.set(Calendar.MINUTE, 0);
				calendar.set(Calendar.SECOND, 0);
				calendar.set(Calendar.MILLISECOND, 0);
				startTime = calendar.getTime();

				calendar.add(Calendar.MONTH, month);
				calendar.add(Calendar.DAY_OF_YEAR, -1);
				endTime = calendar.getTime();
				if (partTask.getLateFinish() == null
						|| partTask.getLateFinish().before(startTime)
						|| partTask.getLateFinish().after(endTime)) {
					continue;
				}

			}

			partTaskListForReturn.add(partTask);

		}
		Collections.sort(partTaskListForReturn, new Comparator<Object>() {
			public int compare(Object o1, Object o2) {
				SPartTask partTask1 = (SPartTask) o1;
				SPartTask partTask2 = (SPartTask) o2;
				int i = 0;
				if (partTask1.getPriority() > partTask2.getPriority()) {
					i = 1;
				}
				return i;
			}
		});
		return partTaskListForReturn;
	}

	 
	public List<SPartTask> filterCanCombineBatch(
			Collection<SPartTask> partTaskList, Map parameters) {

		List<SPartTask> partTaskListForReturn = new LinkedList<SPartTask>();
		Integer priority = (Integer) parameters.get("priority");

		String model = (String) parameters.get("model");
		String drawingId = (String) parameters.get("drawingId");
		String batchNums = (String) parameters.get("batchNums");
		String[] bNums = batchNums.split(",");
		Integer planGrade = (Integer) parameters.get("planGrade");
		Date lateFinish = (Date) parameters.get("lateFinish");
		Integer isCritical = (Integer) parameters.get("isCritical");
		Integer month = (Integer) parameters.get("month");
		boolean isAdd = true;
		for (SPartTask partTask : partTaskList) {
			isAdd = true;
			for (String batchNum : bNums) {
				if (!StringOper.equalsPrecise(drawingId, partTask
						.getDrawingId())) {
					isAdd = false;
					continue;
				}
				if (StringOper.equalsPrecise(batchNum, partTask.getBatchNum())) {
					isAdd = false;
					continue;
				}
			}
			if (isAdd)
				partTaskListForReturn.add(partTask);
		}

		Collections.sort(partTaskListForReturn, new Comparator<Object>() {
			public int compare(Object o1, Object o2) {
				SPartTask partTask1 = (SPartTask) o1;
				SPartTask partTask2 = (SPartTask) o2;
				int i = 0;
				if (partTask1.getPriority() > partTask2.getPriority()) {
					i = 1;
				}
				return i;
			}
		});
		return partTaskListForReturn;

	}

	public List<SPartTask> filter(Collection<SPartTask> partTaskList,
			Map parameters) {
		List<SPartTask> partTaskListForReturn = new LinkedList<SPartTask>();

		Integer priority = (Integer) parameters.get("priority");

		String model = (String) parameters.get("model");
		String drawingId = (String) parameters.get("drawingId");
		String batchNum = (String) parameters.get("batchNum");
		Integer planGrade = (Integer) parameters.get("planGrade");
		Date lateFinish = (Date) parameters.get("lateFinish");
		Integer isCritical = (Integer) parameters.get("isCritical");
		Integer month = (Integer) parameters.get("month");
		for (SPartTask partTask : partTaskList) {

			if (!StringOper.equals(model, partTask.getModel()))
				continue;
			if (!StringOper.equals(drawingId, partTask.getDrawingId()))
				continue;
			if (!StringOper.equals(batchNum, partTask.getBatchNum()))
				continue;

			if (priority != null && priority > 0) {
				int pp = Integer.parseInt(String
						.valueOf(partTask.getPriority()).substring(0, 1));
				if (!priority.equals(pp))
					continue;
			}
			if (planGrade != null && planGrade > 0) {
				if (!partTask.getPlanGrade().equals(planGrade))
					continue;
			}
			if (isCritical != null) {
				if (!(isCritical).equals(partTask.getIsCritical()))
					// if (!partTask.getIsCritical().equals(isCritical))
					continue;
			}
			if (lateFinish != null
					&& (partTask.getLateFinish() == null || partTask
							.getLateFinish().after(lateFinish)))
				continue;

			// add by hba 用于按期过滤零件任务
			if (month != null && month < 3) {
				Date startTime, endTime;
				Calendar calendar = Calendar.getInstance();
				calendar.add(Calendar.MONTH, month);
				calendar.set(Calendar.DAY_OF_MONTH, 1);
				calendar.set(Calendar.HOUR, 0);
				calendar.set(Calendar.MINUTE, 0);
				calendar.set(Calendar.SECOND, 0);
				calendar.set(Calendar.MILLISECOND, 0);
				startTime = calendar.getTime();

				calendar.add(Calendar.MONTH, month + 1);
				calendar.add(Calendar.DAY_OF_YEAR, -1);
				endTime = calendar.getTime();
				if (partTask.getLateFinish() == null
						|| partTask.getLateFinish().before(startTime)
						|| partTask.getLateFinish().after(endTime)) {
					continue;
				}

			}

			partTaskListForReturn.add(partTask);

		}
		Collections.sort(partTaskListForReturn, new Comparator<Object>() {
			public int compare(Object o1, Object o2) {
				SPartTask partTask1 = (SPartTask) o1;
				SPartTask partTask2 = (SPartTask) o2;
				int i = 0;
				if (partTask1.getPriority() > partTask2.getPriority()) {
					i = 1;
				}
				return i;
			}
		});
		return partTaskListForReturn;
	}

	public void initRemainWork(SPartTask partTask, SOperationTask timeStone) {
		double remainWork = 0;
		double estiWork = 0;
		SOperationTask predSo = null;
		if (timeStone != null) {
			for (SOperationTask operationTask : partTask.getOperationTaskList()) {
				if (operationTask.getOperationId() <= timeStone
						.getOperationId()) {

					remainWork += operationTask.getEstiTaskWork()
							+ linkLagCal.getLinkLag(predSo, operationTask);

				}
				predSo = operationTask;
			}
		} else {
			for (SOperationTask operationTask : partTask.getOperationTaskList()) {

				if (operationTask.getGroupTask() != null)
					estiWork = operationTask.getGroupTask().getEstiTaskWork();
				else
					estiWork = operationTask.getEstiTaskWork();
				remainWork += estiWork
						+ linkLagCal.getLinkLag(predSo, operationTask);
				predSo = operationTask;
			}
		}

		partTask.setRemainWork(remainWork);
	}

	/*
	 * 创建缺省链接
	 */
	public void createDefaultLink(SPartTask partTask) {
		ScheduleScheme scheme = partTask.getScheme();
		List<SOperationTask> opList = partTask.getOperationTaskList();
		for (int i = 1; i < opList.size(); i++) {
			SOperationTask opTask = opList.get(i);
			if (opTask.getPredLinkSet().size() == 0) {
				SOperationLink operationLink = new SOperationLink();
				operationLink.setPredecessorUid(opList.get(i - 1).getTaskUid());
				operationLink.setSuccessorUid(opTask.getTaskUid());
				operationLink.setLinkLag(0);
				operationLink.setIsIneffective(1);
				operationLink.setLockLevel(0);
				operationLink.setLinkQty(opTask.getPlanQty());
				operationLink.setLinkType(1);
				operationLink.setPredOperationTask(opList.get(i - 1));
				operationLink.setSuccOperationTask(opTask);
				opTask.getPredLinkSet().add(operationLink);
				opList.get(i - 1).getSuccLinkSet().add(operationLink);
				scheme.getAllOperationLinkMap().put(operationLink.getLinkKey(),
						operationLink);

			}
		}
	}

	public void calcSlack(SPartTask partTask) {
		if (partTask == null)
			return;

		double slack = 999999;// 很大的松弛率
		partTask.setSlackFactor(slack);
		if (partTask.getOperationTaskList() == null
				|| partTask.getOperationTaskList().size() == 0)
			return;

		setNextTimeStone(partTask);

		double remainTime = 0;
		if (partTask.getNextTimeStone() != null) {
			initRemainWork(partTask, partTask.getNextTimeStone());
			remainTime = (partTask.getNextTimeStone().getLateFinish().getTime() - partTask
					.getScheme().getScheduleStart().getTime()) / 60000;

		} else {
			initRemainWork(partTask, null);
			Date lateFinish = partTask.getLateFinish() == null ? partTask
					.getScheme().getScheduleFinish() : partTask.getLateFinish();
			remainTime = (lateFinish.getTime() - partTask.getScheme()
					.getScheduleStart().getTime()) / 60000;
		}
		double remainWork = partTask.getRemainWork();
		if (remainWork > 0) {
			// 松弛率计算公式
			slack = remainTime / remainWork;
			partTask.setSlackFactor(slack);
		}
	}

	// todo
	// 动态松弛
	// 没有考虑工序周转延迟
	public void calcSlack(SPartTask partTask,
			SOperationTask currentOperationTask) {
		double remainWork = 0;
		double remainTime = 0;
		double slackFactor = 0;
		Date lateFinish = partTask.getLateFinish() == null ? partTask
				.getScheme().getScheduleFinish() : partTask.getLateFinish();

		for (SOperationTask operationTask : partTask.getOperationTaskList()) {
			if (operationTask.getOperationId() >= currentOperationTask
					.getOperationId()) {
				remainWork += operationTask.getEstiTaskWork();
				if (operationTask.getLateFinish() != null
						&& operationTask.getLateFinish().before(lateFinish)) {
					lateFinish = operationTask.getLateFinish();
					break;
				}
			}
		}
		Date earlyStart = partTask.getEarlyStart() != null
				&& partTask.getEarlyStart().after(
						partTask.getScheme().getScheduleStart()) ? partTask
				.getEarlyStart() : partTask.getScheme().getScheduleStart();
		if (currentOperationTask.getControlEarlyStart() != null
				&& currentOperationTask.getControlEarlyStart()
						.after(earlyStart))
			earlyStart = currentOperationTask.getControlEarlyStart();

		remainTime = (lateFinish.getTime() - earlyStart.getTime()) / 60000;
		if (remainWork > 0)
			slackFactor = remainTime / remainWork;
		else
			slackFactor = 999999;// 很大的松弛率
		currentOperationTask.setSlackFactor(slackFactor);
	}

	public double getDynamicSlack(SPartTask partTask) {
		return 0;
	}

	/**
	 * 
	 */
	public void setStartEndTimeOfPartTask(SPartTask partTask) {
		Iterator<SOperationTask> interator = partTask.getOperationTaskList()
				.iterator();
		SOperationTask operationTask = interator.next();
		Date planStart = operationTask.getPlanStart();
		Date planFinish = operationTask.getPlanFinish();
		while (interator.hasNext()) {
			operationTask = interator.next();
			if (operationTask.getPlanStart().before(planStart)) {
				planStart = operationTask.getPlanStart();
			}
			if (operationTask.getPlanFinish().after(planFinish)) {
				planFinish = operationTask.getPlanFinish();
			}
		}
		partTask.setPlanStart(planStart);
		partTask.setPlanFinish(planFinish);
		if (partTask.getControlFinish() != null) {
			int delayDays = (int) Math.round((partTask.getPlanFinish()
					.getTime() - partTask.getControlFinish().getTime())
					/ (60000 * 1440));
			if (delayDays < 0) {
				delayDays -= 1;
			}
			if (delayDays > 0) {
				delayDays += 1;
			}
			partTask.setDelayDays(delayDays);
		}
		// partTask.setCurrentOperation(partTask.getOperationTaskList().get(0));
	}

	/**
	 * use partTask2.value update partTask1.value
	 * 
	 * @param partTask1
	 *            Original partTask
	 * @param partTask2
	 *            New partTask
	 */
	public void updatePartTask(SPartTask partTask1, SPartTask partTask2) {
		// BeanUtils beanUtils = new BeanUtils();
		// partTask2.setOperationTaskList(partTask1.getOperationTaskList());
		// try {
		// beanUtils.copyProperties(partTask1, partTask2);
		// } catch (IllegalAccessException e) {
		// // TODO Auto-generated catch block
		// e.printStackTrace();
		// } catch (InvocationTargetException e) {
		// // TODO Auto-generated catch block
		// e.printStackTrace();
		// }
		// setPriority(partTask1);
	}

	public void setNextTimeStone(SPartTask partTask) {
		SOperationTask temp = null;
		if (partTask.getOperationTaskList() == null)
			return;
		for (SOperationTask operationTask : partTask.getOperationTaskList()) {
			if (operationTask.getLateFinish() != null) {
				temp = operationTask;
				partTask.setNextTimeStone(temp);
				break;
			}
		}

	}

	public SPartTask combineBatch(List<SPartTask> combineBatchList, int mode)
			throws Exception {
		// TODO Auto-generated method stub
		SPartTask newTask;
		ScheduleScheme scheme;
		SPartTask destPartTask;
		List<SOperationTask> opList;
		// 用来临时存储uid之间的对应关系
		Map<String, SOperationTask> taskUidMap;

		newTask = new SPartTask();
		try {
			BeanUtils beanUtils = new BeanUtils();
			if (combineBatchList == null || combineBatchList.size() <= 1) {
				throw new Exception("请至少选择两条合批任务");
			}
			// 有效性验证
			for (SPartTask partTask : combineBatchList) {
				if (partTask.getTaskScheduleType() == SPartTask.TASKSCHEDULETYPE_COMBINEBATCH)
					throw new Exception("批次 " + partTask.getBatchNum()
							+ "为合批任务，请先进行取消合批操作");

			}

			SPartTask tempTask = combineBatchList.get(0);
			scheme = tempTask.getScheme();
			double planQty = 0d;
			double demandLinkQty = 0d;
			int count = 0;
			String batchNum = "";
			Date lateFinish = scheme.getScheduleFinish();
			destPartTask = tempTask;
			Collections.sort(combineBatchList, new Comparator<Object>() {
				public int compare(Object o1, Object o2) {
					SPartTask partTask1 = (SPartTask) o1;
					SPartTask partTask2 = (SPartTask) o2;
					int i = 0;
					if (partTask1.getBatchNum().compareTo(
							partTask2.getBatchNum()) > 0) {
						i = 1;
					}
					return i;
				}
			});
			ObjectOperation.copyAttributes(tempTask, newTask);
			newTask.setScheme(scheme);
			for (SPartTask partTask : combineBatchList) {
				planQty += partTask.getPlanQty();
				demandLinkQty += partTask.getDemandLinkQty();
				batchNum += partTask.getBatchNum() + ",";
				// 取工序数最大的零件任务
				if (partTask.getOperationTaskList().size() > count) {
					count = partTask.getOperationTaskList().size();
					destPartTask = partTask;
				}
				if (partTask.getLateFinish() != null
						&& partTask.getLateFinish().before(lateFinish)) {
					lateFinish = partTask.getLateFinish();
				}

				// try {
				// BeanUtils.copyProperties(newTask, tempTask);
				//					
				//					
				// } catch (IllegalAccessException e) {
				// // TODO Auto-generated catch block
				// e.printStackTrace();
				// } catch (InvocationTargetException e) {
				// // TODO Auto-generated catch block
				// e.printStackTrace();
				// }
			}
			batchNum = batchNum.substring(0, batchNum.length() - 1);
			newTask.setLateFinish(lateFinish);
			newTask.setControlFinish(lateFinish);
			newTask.setPlanQty(planQty);
			newTask.setDemandLinkQty(demandLinkQty);
			newTask.setBatchNum(batchNum);
			newTask.setTaskUid(IdentityGenerator.GetIdentityString());

			opList = newTask.getOperationTaskList();
			SOperationTask[][] operationTasks = new SOperationTask[combineBatchList
					.size()][count];

			for (int i = 0; i < destPartTask.getOperationTaskList().size(); i++) {
				operationTasks[0][i] = destPartTask.getOperationTaskList().get(
						i);
			}
			int j = 1;
			for (SPartTask partTask : combineBatchList) {
				if (partTask != destPartTask) {
					for (int i = 0; i < partTask.getOperationTaskList().size(); i++) {
						SOperationTask temp = partTask.getOperationTaskList()
								.get(i);
						for (int k = i; k < count; k++) {
							if (temp.getOperationIdDesc().equals(
									operationTasks[0][k].getOperationIdDesc())) {
								operationTasks[j][k] = temp;
								break;
							}
						}
					}
					j++;
				}
			}
			taskUidMap = new HashMap<String, SOperationTask>();
			for (int i = 0; i < count; i++) {
				SOperationTask newOpTask = new SOperationTask();
				double planqty = 0d;
				double completeqty = 0d;
				for (int k = 0; k < combineBatchList.size(); k++) {
					if (operationTasks[k][i] != null) {
						planqty += operationTasks[k][i].getPlanQty();
						completeqty += operationTasks[k][i].getCompleteQty();

					}
				}
				ObjectOperation.copyAttributes(operationTasks[0][i], newOpTask);
				newOpTask.setScheme(scheme);
				// try {
				// beanUtils.copyProperties(,operationTasks[0][i] );
				// newOpTask.setScheme(scheme);
				// } catch (IllegalAccessException e) {
				// // TODO Auto-generated catch block
				// e.printStackTrace();
				// } catch (InvocationTargetException e) {
				// // TODO Auto-generated catch block
				// e.printStackTrace();
				// }

				newOpTask.setTaskUid(IdentityGenerator.GetIdentityString());

				taskUidMap.put(operationTasks[0][i].getTaskUid(), newOpTask);

				newOpTask.setBatchNum(batchNum);
				newOpTask.setPlanQty(planqty);
				newOpTask.setCompleteQty(completeqty);
				// 工序初始化中已经集中处理i该类操作
				// newOpTask.calTaskWork();
				// newOpTask.setAlterResourceList(operationTasks[0][i]
				// .getAlterResourceList());
				// newOpTask.setPredLinkSet(new HashSet<SOperationLink>());
				// newOpTask.setSuccLinkSet(new HashSet<SOperationLink>());
				newOpTask.setParentTask(newTask);

				newOpTask
						.setTaskScheduleType(newOpTask.TASKSCHEDULETYPE_COMBINEBATCH);

				if (newOpTask.getDeptUid() == null)
					newOpTask.setDeptUid(scheme.getDeptUid());

				this.scheduleOperationTaskManager.init(scheme, newOpTask);

				scheme.getAllOperationTaskMap().put(newOpTask.getTaskUid(),
						newOpTask);
				this.scheduleOperationTaskManager.add(newOpTask);

				opList.add(newOpTask);
			}

			// todo
			// 这里只更新了同零件任务的所有链接，
			// 万一出现非同一零件任务的链接
			// 是存在问题的
			Map<String, SOperationLink> oldLinkMap = getSOperationLink(destPartTask);
			for (SOperationLink oldLink : oldLinkMap.values()) {
				SOperationTask predSo = taskUidMap.get(oldLink
						.getPredecessorUid());
				SOperationTask succSo = taskUidMap.get(oldLink
						.getSuccessorUid());
				if (predSo != null && succSo != null)
					scheduleLinkManager.addLink(predSo, succSo, oldLink
							.getLinkType(), oldLink.getLinkLag());
			}
			// newTask.setOperationTaskList(opList);

			newTask
					.setTaskScheduleType(SPartTask.TASKSCHEDULETYPE_COMBINEBATCH);// 标识合批后产生的任务
			scheme.getAllPartTaskMap().put(newTask.getTaskUid(), newTask);
			this.add(newTask);

			// 删除合批之前的工序任务
			// 因为分批要按照新的工艺路线进行编辑，原来的任务已经无用
			for (SPartTask partTask : combineBatchList) {

				List<SOperationTask> ops = new ArrayList<SOperationTask>();// todo,只能这样做，否则会出现并行错误
				for (SOperationTask so : partTask.getOperationTaskList()) {
					ops.add(so);

				}
				for (SOperationTask so : ops) {
					scheduleOperationTaskManager.removeOperationTask(so, true);
				}

			}

			if (newTask.getTaskScheduleState() == SPartTask.TASKSCHEDULESTATE_STARTED) {

			}

			newTask.setTaskScheduleState(SPartTask.TASKSCHEDULESTATE_WAITING);

			this.intoSchedule(newTask);

			for (SPartTask sp : combineBatchList) {
				// if (sp.getTaskScheduleState() ==
				// SPartTask.TASKSCHEDULESTATE_STARTED)
				this.outSchedule(sp, false);

			}

			// newTask.setCombinedBatchs(combineBatchList);
			// calcSlack(newTask);
			taskUidMap = null;
		} catch (RuntimeException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		return newTask;
	}

	public void sortByPriorityAndSlack(List<SPartTask> partTaskList) {
		if (partTaskList == null || partTaskList.isEmpty()) {
			return;
		} else {
			Collections.sort(partTaskList, new Comparator<Object>() {
				public int compare(Object o1, Object o2) {
					SPartTask partTask1 = (SPartTask) o1;
					SPartTask partTask2 = (SPartTask) o2;
					int i = 0;
					if (partTask1.getPriority() > partTask2.getPriority()
							|| (partTask1.getPriority() == partTask2
									.getPriority() && partTask1
									.getSlackFactor() > partTask2
									.getSlackFactor())) {
						i = 1;
					}
					if (partTask1.getPriority() < partTask2.getPriority()
							|| (partTask1.getPriority() == partTask2
									.getPriority() && partTask1
									.getSlackFactor() < partTask2
									.getSlackFactor()))
						i = 1;
					return i;
				}
			});

		}

	}

	public void sortByPriorityDrawingIdAndBatchNum(List<SPartTask> partTaskList) {
		if (partTaskList == null || partTaskList.isEmpty()) {
			return;
		} else {
			Collections.sort(partTaskList, new Comparator<Object>() {
				public int compare(Object o1, Object o2) {
					SPartTask partTask1 = (SPartTask) o1;
					SPartTask partTask2 = (SPartTask) o2;
					int i = 0;
					if (partTask1.getPriority() > partTask2.getPriority()
							|| (partTask1.getPriority() == partTask2
									.getPriority() && partTask1.getDrawingId()
									.compareTo(partTask2.getDrawingId()) > 0)

							|| ((partTask1.getPriority() == partTask2
									.getPriority() && partTask1.getDrawingId()
									.compareTo(partTask2.getDrawingId()) == 0) && partTask1
									.getBatchNum().compareTo(
											partTask2.getBatchNum()) > 0)) {
						i = 1;
					}
					return i;
				}
			});

		}

	}

	public void sortByDrawingIdAndBatchNum(List<SPartTask> partTaskList) {
		if (partTaskList == null || partTaskList.isEmpty()) {
			return;
		} else {
			Collections.sort(partTaskList, new Comparator<Object>() {
				public int compare(Object o1, Object o2) {
					SPartTask partTask1 = (SPartTask) o1;
					SPartTask partTask2 = (SPartTask) o2;
					int i = 0;
					if ((partTask1.getDrawingId().compareTo(
							partTask2.getDrawingId()) > 0)
							|| ((partTask1.getDrawingId().compareTo(
									partTask2.getDrawingId()) == 0) && partTask1
									.getBatchNum().compareTo(
											partTask2.getBatchNum()) > 0)) {
						i = 1;
					}
					if ((partTask1.getDrawingId().compareTo(
							partTask2.getDrawingId()) < 0)
							|| ((partTask1.getDrawingId().compareTo(
									partTask2.getDrawingId()) == 0) && partTask1
									.getBatchNum().compareTo(
											partTask2.getBatchNum()) < 0)) {
						i = -1;
					}
					return i;
				}
			});

		}

	}

	public void autoCombineBatch(ScheduleScheme scheme) throws Exception {
		// TODO Auto-generated method stub
		// List<SPartTask> partTaskList =(List<SPartTask>)
		// scheme.getAllPartTaskMap().values().toArray();

		cancelAllCombineBatch(scheme);

		List<SPartTask> partTaskList = new ArrayList<SPartTask>();
		for (SPartTask sp : scheme.getAllPartTaskMap().values()) {
			partTaskList.add(sp);
		}
		sortByDrawingIdAndBatchNum(partTaskList);
		List<List<SPartTask>> partTaskGroups = new ArrayList<List<SPartTask>>();
		List<SPartTask> tempTaskGroup = new ArrayList<SPartTask>();
		if (partTaskList.size() != 0) {
			tempTaskGroup.add(partTaskList.get(0));
			for (int i = 1; i < partTaskList.size(); i++) {

				if (partTaskList.get(i).getDrawingId().equals(
						partTaskList.get(i - 1).getDrawingId())
						&& partTaskList.get(i).getCurrentOperation()
								.getOperationIdDesc().equals(
										partTaskList.get(i - 1)
												.getCurrentOperation()
												.getOperationIdDesc())) {
					tempTaskGroup.add(partTaskList.get(i));

				} else {
					partTaskGroups.add(tempTaskGroup);
					tempTaskGroup = new ArrayList<SPartTask>();
					tempTaskGroup.add(partTaskList.get(i));
				}
			}
		}
		for (List<SPartTask> partTaskGroup : partTaskGroups) {
			if (partTaskGroup.size() >= 2) {
				Collections.sort(partTaskList, new Comparator<Object>() {
					public int compare(Object o1, Object o2) {
						SPartTask partTask1 = (SPartTask) o1;
						SPartTask partTask2 = (SPartTask) o2;
						int i = 0;
						if (partTask1.getBatchNum().compareTo(
								partTask2.getBatchNum()) > 0) {
							i = 1;
						}
						return i;
					}
				});
				SPartTask combinedBatch = combineBatch(partTaskGroup, 1);

				// //将原来的组合全部移除
				// for(SPartTask sp:partTaskGroup)
				// {
				// scheme.getAllPartTaskMap().remove(sp.getTaskUid());
				// }

				// scheme.getCombineBatchList().add(combinedBatch);

				// this.scheduleTaskDao.saveConstraint(scheme.getScheduleUid(),
				// combinedBatch, 1, "");

			}

		}

	}

	private SPartTask newSplitBatchPro(SPartTask partTask, SOperationTask opTask)
			throws Exception {
		SPartTask newTask = new SPartTask();
		ScheduleScheme scheme = partTask.getScheme();
		ObjectOperation.copyAttributes(partTask, newTask);
		newTask.setScheme(scheme);
		newTask.setLateFinish(opTask.getLateFinish());

		newTask.setPlanQty(opTask.getPlanQty());
		newTask.setDemandLinkQty(0.0);
		newTask.setBatchNum(opTask.getBatchNum());
		newTask.setTaskUid(IdentityGenerator.GetIdentityString());
		// by hba 用于初始化调度状态为待调度，否则后面不会再加入排产集合。
		newTask.setTaskScheduleState(SPartTask.TASKSCHEDULESTATE_WAITING);

		List<SOperationTask> operationTaskList = new ArrayList<SOperationTask>();
		newTask.setOperationTaskList(operationTaskList);
		for (SOperationTask operationTask : partTask.getOperationTaskList()) {
			// 分批bug，新分出的批次应该在选择的开始工序就分批了，所以不要有等于 by hba
			if (operationTask.getOperationId() < opTask.getOperationId())
				continue;

			SOperationTask newOpTask = new SOperationTask();
			ObjectOperation.copyAttributes(operationTask, newOpTask);
			newOpTask.setScheme(scheme);

			newOpTask.setTaskUid(IdentityGenerator.GetIdentityString());

			newOpTask.setBatchNum(newTask.getBatchNum());
			newOpTask.setPlanQty(newTask.getPlanQty());
			newOpTask.setCompleteQty(newTask.getCompleteQty());

			newOpTask.setParentTask(newTask);

			newOpTask
					.setTaskScheduleType(newOpTask.TASKSCHEDULETYPE_SPLITBATCH);

			if (newOpTask.getDeptUid() == null)
				newOpTask.setDeptUid(scheme.getDeptUid());

			this.scheduleOperationTaskManager.init(scheme, newOpTask);

			scheme.getAllOperationTaskMap().put(newOpTask.getTaskUid(),
					newOpTask);
			this.scheduleOperationTaskManager.add(newOpTask);

			operationTaskList.add(newOpTask);

		}
		// lqm todo
		// 暂时先用顺序链接
		for (int i = 0; i < operationTaskList.size() - 1; i++) {
			SOperationTask predTask = operationTaskList.get(i);
			scheduleLinkManager.addLink(operationTaskList.get(i),
					operationTaskList.get(i + 1), SOperationLink.LINKTYPE_FTS,
					0);

		}

		newTask.setTaskScheduleType(SPartTask.TASKSCHEDULETYPE_SPLITBATCH);// 标识合批后产生的任务

		scheme.getAllPartTaskMap().put(newTask.getTaskUid(), newTask);
		this.init(scheme, newTask);
		this.add(newTask);
		this.intoSchedule(newTask);

		return newTask;
	}

	private void oldSplitBatchPro(SPartTask partTask, SOperationTask opTask)
			throws Exception {

		for (SOperationTask operationTask : partTask.getOperationTaskList()) {
			// 分批bug，应该在选择的开始工序就分批了，所以要有等于 by hba
			if (operationTask.getOperationId() >= opTask.getOperationId()) {
				operationTask.setPlanQty(opTask.getPlanQty());
				operationTask.calTaskWork();
			}
		}
		partTask.setPlanQty(opTask.getPlanQty());
		partTask.setLateFinish(opTask.getLateFinish());
		// 加上这句话可以解决分批后重新打开计划原批次数量不变的问题 hba
		this.update(partTask);
	}

	// 取消分批
	public void cancelSplitBatch(SPartTask mainBatch,
			List<SPartTask> splitedBatchs) throws Exception {

		ScheduleScheme scheme = mainBatch.getScheme();
		if (splitedBatchs == null || splitedBatchs.size() <= 1)
			return;
		// throw new Exception("子批不存在或者子批数量为0！\n"
		// + partTask.toFriendlyString());

		List<SPartTask> onlySplitedBatchs = new ArrayList<SPartTask>();
		Double sumPlanQty = mainBatch.getPlanQty();
		Double sumCompleteQty = mainBatch.getCompleteQty();
		for (SPartTask childBatch : splitedBatchs) {

			if (childBatch != mainBatch) {
				onlySplitedBatchs.add(childBatch);
				sumPlanQty += childBatch.getPlanQty();
				sumCompleteQty += childBatch.getCompleteQty();
			}

		}

		mainBatch.setPlanQty(sumPlanQty);
		mainBatch.setCompleteQty(sumCompleteQty);

		this.updatePartTask(scheme, mainBatch);

		for (SOperationTask mainSO : mainBatch.getOperationTaskList()) {
			sumPlanQty = mainSO.getPlanQty();
			sumCompleteQty = mainSO.getCompleteQty();
			for (SPartTask childBatch : onlySplitedBatchs) {
				for (SOperationTask childSO : childBatch.getOperationTaskList()) {
					if (childSO.getOperationIdDesc().equals(
							mainSO.getOperationIdDesc())) {
						sumPlanQty += childSO.getPlanQty();
						sumCompleteQty += childSO.getCompleteQty();
					}
				}

			}

			mainSO.setPlanQty(sumPlanQty);
			mainSO.setCompleteQty(sumCompleteQty);
			this.scheduleOperationTaskManager.updateOperationTask(scheme,
					mainSO);

		}

		for (SPartTask childBatch : onlySplitedBatchs) {
			log.debug("取消分批:" + childBatch);
			this.removePartTask(childBatch, true);
		}
	}

	 
	public void cancelSplitBatchWithEvent(SPartTask mainBatch,
			List<SPartTask> splitedBatchs) throws Exception {
		ScheduleScheme scheme = mainBatch.getScheme();
		if (splitedBatchs == null || splitedBatchs.size() <= 1)
			return;
		// throw new Exception("子批不存在或者子批数量为0！\n"
		// + partTask.toFriendlyString());

		List<SPartTask> onlySplitedBatchs = new ArrayList<SPartTask>();
		Double sumPlanQty = mainBatch.getPlanQty();
		Double sumCompleteQty = mainBatch.getCompleteQty();
		for (SPartTask childBatch : splitedBatchs) {

			if (childBatch != mainBatch) {
				onlySplitedBatchs.add(childBatch);
				sumPlanQty += childBatch.getPlanQty();
				sumCompleteQty += childBatch.getCompleteQty();
			}
		}

		// 写日志
		Element taskElement = new Element("PARTTASK_CANCELSPLITBATCH");
		taskElement.setAttribute("taskUid", mainBatch.getTaskUid());
		taskElement.setAttribute("partUid", mainBatch.getPartUid());
		taskElement.setAttribute("drawingId", mainBatch.getDrawingId());
		taskElement.setAttribute("partName", mainBatch.getPartName());
		taskElement.setAttribute("batchNum", mainBatch.getBatchNum());

		for (SPartTask splitPartTask : splitedBatchs) {
			SOperationTask splitOpTask = new SOperationTask();
			for (SOperationTask op : splitPartTask.getOperationTaskList()) {
				if (op.getOperationIdDesc().equals(
						splitPartTask.getCurrentOperation()
								.getOperationIdDesc())) {
					splitOpTask = op;
					break;
				}
			}
			Element splitTaskElement = new Element("splitTask");
			splitTaskElement.setAttribute("batchNum", splitPartTask
					.getBatchNum());
			// 数量只能有工序的数量
			splitTaskElement.setAttribute("planQty", String.valueOf(splitOpTask
					.getPlanQty()));
			splitTaskElement.setAttribute("operationIdDesc", String
					.valueOf(splitPartTask.getCurrentOperation()
							.getOperationIdDesc()));
			taskElement.addContent(splitTaskElement);
		}

		mainBatch.setPlanQty(sumPlanQty);
		mainBatch.setCompleteQty(sumCompleteQty);

		taskElement.setAttribute("planQty", String.valueOf(mainBatch
				.getPlanQty()));

		this.updatePartTask(scheme, mainBatch);

		for (SOperationTask mainSO : mainBatch.getOperationTaskList()) {
			sumPlanQty = mainSO.getPlanQty();
			sumCompleteQty = mainSO.getCompleteQty();
			for (SPartTask childBatch : onlySplitedBatchs) {
				for (SOperationTask childSO : childBatch.getOperationTaskList()) {
					if (childSO.getOperationIdDesc().equals(
							mainSO.getOperationIdDesc())) {
						sumPlanQty += childSO.getPlanQty();
						sumCompleteQty += childSO.getCompleteQty();
					}
				}
			}

			mainSO.setPlanQty(sumPlanQty);
			mainSO.setCompleteQty(sumCompleteQty);

			this.scheduleOperationTaskManager.updateOperationTask(scheme,
					mainSO);
		}

		for (SPartTask childBatch : onlySplitedBatchs) {
			log.debug("取消分批:" + childBatch);
			this.removePartTask(childBatch, true);
		}
		this.scheduleOperationRecordManager.writeCancelSplitBatchLog(scheme,
				mainBatch, splitedBatchs);
		this.scheduleEventManager.writeOperLog(scheme,
				ScheduleEvent.EVENTTYPE_PARTTASK_CANCELSPLITBATCH, taskElement);

	}

	// 分批
	public List<SPartTask> splitBatch(SPartTask partTask,
			List<SOperationTask> splitedBatchs) throws Exception {

		if (partTask.getCombinedBatchs() != null
				&& partTask.getCombinedBatchs().size() > 0)
			throw new Exception("请先将任务取消合批！" + partTask);

		List<SPartTask> splitBatchList = new ArrayList<SPartTask>();

		boolean useOld = false;
		for (SOperationTask opTask : splitedBatchs) {

			if (opTask.getBatchNum().equals(partTask.getBatchNum())) {
				useOld = true;
				this.oldSplitBatchPro(partTask, opTask);
			} else {
				splitBatchList.add(this.newSplitBatchPro(partTask, opTask));
			}

		}
		// SPartTask.TASKSCHEDULESTATE_STARTED)
		if (!useOld)
			this.outSchedule(partTask, false);
		// 创建新老批次的链接关系
		ScheduleScheme scheme = partTask.getScheme();
		SOperationTask predSo = null;
		for (SOperationTask so1 : partTask.getOperationTaskList()) {
			if (so1.getOperationIdDesc().equals(
					splitedBatchs.get(0).getOperationIdDesc())) {
				predSo = so1;
				break;
			}
		}

		// lqm to
		// 暂时先建在工序上，以后应该考虑建在零件上
		// 应该考虑是否分批次先走
		// 先走的任务设置开始于开始链接，然后考虑固定数量延迟，表示分批次先走
		if (predSo != null) {
			for (SPartTask newsp : splitBatchList) {
				this.scheduleLinkManager.addLink(predSo, newsp
						.getOperationTaskList().get(0), 1, 0);
			}
		}

		// hba 建立与订单的关联关系
		String scheduleUid = partTask.getScheme().getScheduleUid();
		partTask.setDemandLinkQty(0.0);
		// 根据任务获取链接关系
		List<DemandSTaskLink> demandTaskLinks = demandSTaskLinkDao
				.getDemandTaskLinksByTask(scheduleUid, partTask.getTaskUid());
		if (demandTaskLinks == null || demandTaskLinks.size() == 0) {
			return splitBatchList;
		}
		HashMap<String, String> demandUidMap = new HashMap<String, String>();
		// 删除未锁定的链接关系
		for (DemandSTaskLink demandSTaskLink : demandTaskLinks) {
			demandUidMap.put(demandSTaskLink.getDemandUid(), "");
			if (demandSTaskLink.getLockLevel() == null
					|| demandSTaskLink.getLockLevel().equals(0))
				demandSTaskLinkManager.delete(demandSTaskLink);
			// demandSTaskLinkManager.deleteUnlockLinksByDemandUid(scheduleUid,
			// demandSTaskLink.getDemandUid());
		}
		List<String> demandUidList = new ArrayList<String>();
		List<Demand> demandList = new ArrayList<Demand>();
		for (String demandUid : demandUidMap.keySet()) {
			Demand demand = demandDao.getById(demandUid);
			demandList.add(demand);
		}
		if (demandList != null && demandList.size() > 0) {
			Collections.sort(demandList, new Comparator<Demand>() {

				 
				public int compare(Demand o1, Demand o2) {
					if (o1.getLateFinish() == null)
						return 1;
					if (o2.getLateFinish() == null)
						return -1;
					return o1.getLateFinish().compareTo(o2.getLateFinish());
				}
			});
		}

		for (Demand demandTemp : demandList) {
			// this.demandSTaskLinkManager.autoCreateLink(scheduleUid, demand);

			float arrangeQty = (float) demandDao.getArrangeQty(demandTemp
					.getDemandUid(), scheduleUid);
//			demandTemp.setArrangeQty((double)arrangeQty);
			Date planFinish = demandDao.getPlanFinish(
					demandTemp.getDemandUid(), scheduleUid);
			demandTemp.setPlanFinish(planFinish);

			double remainQty = this.demandDao.getRemainQty(demandTemp
					.getDemandUid(), scheduleUid);
//			demandTemp.setRemainQty(remainQty);

			// 稳妥初始化已安排数量，为了保险
//			demandTemp.setArrangeQty((double)demandSTaskLinkManager.calArrangeQty(
//					scheduleUid, demandTemp));

			// 指令需求数与指令已安排数量比较
			if (demandTemp.getDueQty() == null) {

				throw new BaseBusinessException("指令需求数量为空，请检查指令");
			}
			if (demandTemp.getDueQty() - demandTemp.getArrangeQty() == 0)
				break;// 已经全部安排

			List<SPartTask> partTasks = new Vector<SPartTask>();
			String partUid = demandTemp.getPartUid();
			partTasks.add(partTask);
			// 两种取零件任务的区别？ 这里没有发现区别
			for (SPartTask p : splitBatchList) {
				partTasks.add(p);
			}
			/**
			 * 对operationid为0的情况进行检查
			 */
			// by lqm
			for (SPartTask p : partTasks) {
				// 稳妥初始化已链接数量
				p.setDemandLinkQty((Double) calDemandLinkQty(p));
				this.update(p);
				p.getCurrentOperation();
				if (p.getCurrentOperation() == null)
					log.warn(p.getCurrentOperation());

			}

			Collections.sort(partTasks, new Comparator<SPartTask>() {
				public int compare(SPartTask partTask1, SPartTask partTask2) {
					if (partTask1.getCurrentOperation() == null
							&& partTask2.getCurrentOperation() == null) {
						return 0;
					} else if (partTask1.getCurrentOperation() == null) {
						return 1;
					} else if (partTask2.getCurrentOperation() == null) {
						return -1;
					}
					if (partTask2.getCurrentOperation().getOperationId() > (partTask1
							.getCurrentOperation().getOperationId()))
						return 1;
					else if (partTask2.getCurrentOperation().getOperationId()
							.equals(
									partTask1.getCurrentOperation()
											.getOperationId()))
						return partTask1.getBatchNum().compareTo(
								partTask2.getBatchNum());// 工序号相等的用批次号
					else {
						return -1;
					}
				}
			});

			for (int j = 0; j < partTasks.size(); j++) {
				SPartTask partTaskTemp = partTasks.get(j);

				// 指令需求数与指令已安排数量比较
				double demandRemainQty = demandTemp.getDueQty()
						- demandTemp.getArrangeQty();
				double partAvailableQty = partTaskTemp.getPlanQty()
						- partTaskTemp.getDemandLinkQty();
				if (demandRemainQty <= 0) {
					break;
				}
				// 任务计划数量和任务已经链接的数量比较
				if (partAvailableQty <= 0) {
					continue;
				}

				if (demandRemainQty <= partAvailableQty) {
					DemandSTaskLink demandTaskLink = new DemandSTaskLink();
					demandTaskLink.setDemandUid(demandTemp.getUuid());
					demandTaskLink.setPartTaskUid(partTaskTemp.getUuid());
					demandTaskLink.setIsInEffect(1);
					demandTaskLink.setLinkQty(demandRemainQty);
					demandTaskLink.setLockLevel(0);
					demandTaskLink.setDependType("1");
					demandTaskLink.setPartTask(partTaskTemp);
					demandTaskLink.setScheduleUid(scheduleUid);
//					demandTemp.setArrangeQty((double)demandTemp.getDueQty()
//							.floatValue());
					partTaskTemp.setDemandLinkQty(partTaskTemp
							.getDemandLinkQty()
							+ demandRemainQty);
					try {
						demandSTaskLinkManager.saveOrUpdateLink(demandTaskLink);

					} catch (BaseBusinessException e) {
						e.printStackTrace();
					}

					break;
				} else {
					DemandSTaskLink demandTaskLink = new DemandSTaskLink();
					demandTaskLink.setDemandUid(demandTemp.getUuid());
					demandTaskLink.setPartTaskUid(partTaskTemp.getUuid());
					demandTaskLink.setIsInEffect(1);
					demandTaskLink.setLinkQty(partAvailableQty);
					demandTaskLink.setLockLevel(0);
					demandTaskLink.setDependType("1");
					demandTaskLink.setPartTask(partTaskTemp);
					demandTaskLink.setScheduleUid(scheduleUid);
					demandTemp.setArrangeQty(demandTemp.getArrangeQty()
							+ (float) partAvailableQty);

					partTaskTemp.setDemandLinkQty(partTaskTemp.getPlanQty()
							.doubleValue());

					// 添加link是会自动进行判断

					try {
						demandSTaskLinkManager.saveOrUpdateLink(demandTaskLink);

					} catch (BaseBusinessException e) {
						e.printStackTrace();
					}
				}
			}

		}

		return splitBatchList;
	}

	public double calDemandLinkQty(SPartTask partTask) {
		// TODO Auto-generated method stub
		double sum = 0d;
		List<DemandSTaskLink> links = demandSTaskLinkManager
				.getEffectedLinksByTaskUid(partTask.getScheme()
						.getScheduleUid(), partTask.getTaskUid());

		if (links != null && links.size() > 0) {
			for (DemandSTaskLink link : links) {
				sum += link.getLinkQty();
			}
		}

		return sum;
	}

	// 分批
	public List<SPartTask> splitBatchWithEvent(SPartTask partTask,
			List<SOperationTask> splitedBatchs) throws Exception {

		if (partTask.getCombinedBatchs() != null
				&& partTask.getCombinedBatchs().size() > 0)
			throw new Exception("请先将任务取消合批！" + partTask);

		List<SPartTask> splitBatchList = new ArrayList<SPartTask>();

		boolean useOld = false;
		for (SOperationTask opTask : splitedBatchs) {

			if (opTask.getBatchNum().equals(partTask.getBatchNum())) {
				useOld = true;
				this.oldSplitBatchPro(partTask, opTask);
			} else {
				splitBatchList.add(this.newSplitBatchPro(partTask, opTask));
			}

		}

		// SPartTask.TASKSCHEDULESTATE_STARTED)
		if (!useOld)
			this.outSchedule(partTask, false);

		// 创建新老批次的链接关系
		ScheduleScheme scheme = partTask.getScheme();
		SOperationTask predSo = null;

		for (SOperationTask so1 : partTask.getOperationTaskList()) {
			if (so1.getOperationIdDesc().equals(
					splitedBatchs.get(0).getOperationIdDesc())) {
				predSo = so1;
				break;
			}
		}

		// lqm to
		// 暂时先建在工序上，以后应该考虑建在零件上
		// 应该考虑是否分批次先走
		// 先走的任务设置开始于开始链接，然后考虑固定数量延迟，表示分批次先走
		if (predSo != null) {
			for (SPartTask newsp : splitBatchList) {
				this.scheduleLinkManager.addLink(predSo, newsp
						.getOperationTaskList().get(0), 1, 0);
			}
		}
		// 写日志
		Element taskElement = new Element("PARTTASK_SPLITBATCH");
		taskElement.setAttribute("taskUid", partTask.getTaskUid());
		taskElement.setAttribute("partUid", partTask.getPartUid());
		taskElement.setAttribute("drawingId", partTask.getDrawingId());
		taskElement.setAttribute("partName", partTask.getPartName());
		taskElement.setAttribute("batchNum", partTask.getBatchNum());
		taskElement.setAttribute("planQty", String.valueOf(partTask
				.getPlanQty()));
		for (SOperationTask splitTask : splitedBatchs) {
			Element splitTaskElement = new Element("splitTask");
			splitTaskElement.setAttribute("batchNum", splitTask.getBatchNum());
			splitTaskElement.setAttribute("planQty", String.valueOf(splitTask
					.getPlanQty()));
			if (splitTask.getBatchNum().equals(partTask.getBatchNum())) {
				splitTaskElement.setAttribute("operationIdDesc", String
						.valueOf(partTask.getCurrentOperation()
								.getOperationIdDesc()));
			} else {
				splitTaskElement.setAttribute("operationIdDesc", String
						.valueOf(splitTask.getOperationIdDesc()));
			}

			taskElement.addContent(splitTaskElement);
		}

		this.scheduleOperationRecordManager.writeSplitBatchLog(scheme,
				partTask, splitedBatchs);
		this.scheduleEventManager.writeOperLog(partTask.getScheme(),
				ScheduleEvent.EVENTTYPE_PARTTASK_SPLITBATCH, taskElement);

		return splitBatchList;
	}

	public void compressOperationTaskByPartTask(SPartTask partTask) {
		// TODO Auto-generated method stub用于压紧一个零件的工序任务
		Date planStart = partTask.getScheme().getPlanStart();
		Date temp = new Date();
		int t = 0;

		for (SOperationTask operationTask : partTask.getOperationTaskList()) {
			if (t == 0) {
				operationTask.setPlanStart(planStart);
				t = 1;
				temp = this.scheduleOperationTaskManager.calcTaskPlanFinish(
						operationTask, operationTask.getPlanStart(),
						operationTask.getEstiPreTime(), operationTask
								.getEstiRunTime(), false);
				operationTask.setPlanFinish(temp);
			}
			operationTask.setPlanStart(temp);
			temp = this.scheduleOperationTaskManager.calcTaskPlanFinish(
					operationTask, operationTask.getPlanStart(), operationTask
							.getEstiPreTime(), operationTask.getEstiRunTime(),
					false);
			operationTask.setPlanFinish(temp);
		}
	}

	public ScheduleOperationTaskManager getScheduleOperationTaskManager() {
		return scheduleOperationTaskManager;
	}

	public void setScheduleOperationTaskManager(
			ScheduleOperationTaskManager scheduleOperationTaskManager) {
		this.scheduleOperationTaskManager = scheduleOperationTaskManager;
	}

	public LinkLagCal getLinkLagCal() {
		return linkLagCal;
	}

	public void setLinkLagCal(LinkLagCal linkLagCal) {
		this.linkLagCal = linkLagCal;
	}

	public void cancelAllCombineBatch(ScheduleScheme scheme) throws Exception {
		if (scheme == null)
			throw new Exception("调度方案为空！");
		List<String> taskuidList = new ArrayList<String>();
		for (SPartTask partTask : scheme.getCombineBatchList()) {

			taskuidList.add(partTask.getTaskUid());
			// System.out.println(partTask.getTaskUid()+i);

		}
		if (taskuidList != null) {
			for (String taskuid : taskuidList) {
				// System.out.println(taskuid);
				cancelCombineBatch(scheme, taskuid);
				// scheme.getPartTaskList().clear();
			}
		}

	}

	public void cancelCombineBatch(ScheduleScheme scheme, String taskUid)
			throws Exception {
		SPartTask partTask = scheme.getAllPartTaskMap().get(taskUid);
		List<SPartTask> combinedBatchs = partTask.getCombinedBatchs();
		if (combinedBatchs != null && combinedBatchs.size() > 0) {
			// throw new Exception("子批不存在或者子批数量为0！\n"
			// + partTask.toFriendlyString());

			for (SPartTask childTask : combinedBatchs) {
				log.debug("取消分批:" + childTask);
				copyPartTask(partTask, childTask);
				this.intoSchedule(childTask);// 进入调度
				this.update(childTask);
			}
			log.debug("删除合批之后的任务！");
			// 减少在removepartask中计算combinebatchns
			// 变成正常了才让删除
			// lqm todo
			// 迟早应该优化的合批任务调度模型
			// partTask.setTaskScheduleType(SPartTask.TASKSCHEDULETYPE_NORMAL);

			this.removePartTask(partTask, true);

		} else {
			throw new Exception("该任务不是一个有效的合批任务！");
		}

	}

	/*
	 * 将一个零件任务的子工序任务及其链接关系copy给另外一个零件任务
	 * 
	 */
	// todo，应该利用一下对象clone技术
	private void copyPartTask(SPartTask fromTask, SPartTask toTask)
			throws Exception {

		ScheduleScheme scheme = fromTask.getScheme();
		List<SOperationTask> opList = toTask.getOperationTaskList();

		List<SOperationTask> ops = new ArrayList<SOperationTask>();// todo,只能这样做，否则会出现并行错误
		for (SOperationTask so : opList) {
			ops.add(so);
		}

		for (SOperationTask so : ops) {
			scheduleOperationTaskManager.removeOperationTask(so, true);
		}
		// 用来临时存储uid之间的对应关系
		Map<String, SOperationTask> taskUidMap = new HashMap<String, SOperationTask>();
		for (SOperationTask so : fromTask.getOperationTaskList()) {
			SOperationTask newOpTask = new SOperationTask();
			ObjectOperation.copyAttributes(so, newOpTask);
			newOpTask.setScheme(scheme);

			// try {
			// BeanUtils.copyProperties(, so);
			// newOpTask.setScheme(scheme);
			// } catch (IllegalAccessException e) {
			// // TODO Auto-generated catch block
			// e.printStackTrace();
			// } catch (InvocationTargetException e) {
			// // TODO Auto-generated catch block
			// e.printStackTrace();
			// }

			newOpTask.setTaskUid(IdentityGenerator.GetIdentityUUID());

			taskUidMap.put(so.getTaskUid(), newOpTask);

			newOpTask.setBatchNum(toTask.getBatchNum());
			newOpTask.setPlanQty(toTask.getPlanQty());
			// newOpTask.setCompleteQty(toTask);
			// todo 完成数比较难于分配
			// newOpTask.calTaskWork();

			// newOpTask.setPredLinkSet(new HashSet<SOperationLink>());
			// newOpTask.setSuccLinkSet(new HashSet<SOperationLink>());
			newOpTask.setParentTask(toTask);

			// newOpTask.setAlterResourceList(so.getAlterResourceList());
			newOpTask.setScheme(scheme);

			this.scheduleOperationTaskManager.init(scheme, newOpTask);
			scheme.getAllOperationTaskMap().put(newOpTask.getTaskUid(),
					newOpTask);
			this.scheduleOperationTaskManager.add(newOpTask);
			opList.add(newOpTask);
		}

		// todo
		// 这里只更新了同零件任务的所有链接，
		// 万一出现非同一零件任务的链接
		// 是存在问题的
		Map<String, SOperationLink> oldLinkMap = getSOperationLink(fromTask);
		for (SOperationLink oldLink : oldLinkMap.values()) {
			SOperationTask predSo = taskUidMap.get(oldLink.getPredecessorUid());
			SOperationTask succSo = taskUidMap.get(oldLink.getSuccessorUid());
			if (predSo != null && succSo != null)
				scheduleLinkManager.addLink(predSo, succSo, oldLink
						.getLinkType(), oldLink.getLinkLag());
		}

		// for (int i = 0; i < opList.size() - 1; i++) {
		// SOperationTask predTask = opList.get(i);
		// if (predTask.getSuccLinkSet().isEmpty()) {
		// SOperationLink newLink = new SOperationLink();
		// newLink.setPredOperationTask(predTask);
		// newLink.setPredecessorUid(predTask.getTaskUid());// by lqm
		// newLink.setSuccOperationTask(opList.get(i + 1));//
		// 这里完全错误，也就是说根本没有用任务中的链接
		// newLink.setSuccessorUid(opList.get(i + 1).getTaskUid());// by
		// // lqm
		// newLink.setLinkType(SOperationLink.LINKTYPE_FTS);
		// newLink.setLockLevel(1);
		// scheme.getAllOperationLinkMap().put(newLink.getLinkUid(),
		// newLink);
		// predTask.getSuccLinkSet().add(newLink);
		// opList.get(i + 1).getPredLinkSet().add(newLink);
		//
		// }
		// }

		taskUidMap = null;

	}

	private Map<String, SOperationLink> getSOperationLink(SPartTask sPartTask) {
		// 这里只更新了同零件任务的所有链接，是存在问题的
		// todo
		Map<String, SOperationLink> linkMap = new HashMap<String, SOperationLink>();
		List<SOperationTask> opList = sPartTask.getOperationTaskList();
		if (opList != null && opList.size() > 0) {
			for (SOperationTask so : opList) {
				if (so.getSuccLinkSet() != null
						&& so.getSuccLinkSet().size() > 0) {
					for (SOperationLink link : (so.getSuccLinkSet())) {
						if (opList.contains(link.getSuccOperationTask()))
							linkMap.put(link.getLinkKey(), link);
					}
				}
			}
		}

		return linkMap;

	}

	public void removeBatchFromCombinedBatch(ScheduleScheme scheme,
			String combinedTaskUid, String removedBatchNums) throws Exception {
		String strBatchNum = "";
		if (scheme != null) {
			String[] batchNums = removedBatchNums.split(",");

			SPartTask combinedBatch = scheme.getAllPartTaskMap().get(
					combinedTaskUid);
			if (combinedBatch != null) {
				List<SPartTask> childPartTasks = combinedBatch
						.getCombinedBatchs();
				for (SPartTask partTask : childPartTasks) {
					boolean bDeleteFlag = false;
					for (String batchNum : batchNums) {
						if (partTask.getBatchNum().equals(batchNum)) {
							bDeleteFlag = true;
							// rootbach暂时应该没有用
							partTask.setRootBatch(true);
							copyPartTask(combinedBatch, partTask);
							this.intoSchedule(partTask);
						}

					}
					if (!bDeleteFlag)
						strBatchNum = strBatchNum + ","
								+ partTask.getBatchNum();
				}
				if (strBatchNum.length() > 0) {
					strBatchNum = strBatchNum
							.substring(1, strBatchNum.length());
				}
				combinedBatch.setBatchNum(strBatchNum);
				if (combinedBatch.getCombinedBatchs().size() <= 1) {
					this.cancelCombineBatch(scheme, combinedBatch.getTaskUid());
				}

			}

		}

	}

	// 临时，取得一个子任务的父任务,应该有更好的零件任务分批模型
	// todo
	public SPartTask getCombineBatch(SPartTask partTask) {
		ScheduleScheme scheme = partTask.getScheme();
		List<SPartTask> combineBatchList = scheme.getCombineBatchList();
		if (combineBatchList != null && combineBatchList.size() > 0) {
			for (SPartTask scp : combineBatchList) {
				// 将其子任务也设置为已经完成
				List<SPartTask> subList = scp.getCombinedBatchs();
				if (subList != null && subList.size() > 0) {
					for (SPartTask subTask : subList) {
						if (subTask.equals(partTask))
							return scp;
					}
				}
			}
		}
		return null;
	}

	public void refreshCombineBatch(SPartTask combinePartTask) {
		try {
			// 刷新数量
			double planQty = 0d;
			ScheduleScheme scheme = combinePartTask.getScheme();
			Date lateFinish = scheme.getScheduleFinish();

			for (SPartTask subBatch : combinePartTask.getCombinedBatchs()) {
				planQty += subBatch.getPlanQty();

				if (subBatch.getLateFinish() != null
						&& subBatch.getLateFinish().before(lateFinish)) {
					lateFinish = subBatch.getLateFinish();
				}
			}
			combinePartTask.setLateFinish(lateFinish);
			this.update(combinePartTask);
			this.changePartTaskQty(combinePartTask.getScheme(),
					combinePartTask, planQty);

			// 由于已经将合批任务的工序任务移除
			// 所以下面这段代码不能用

			/*
			 * List<SOperationTask> removedCombineOperationList= new ArrayList<SOperationTask>();
			 * 
			 * for (SOperationTask combineSo :
			 * combinePartTask.getOperationTaskList()) {
			 * combineSo.setPlanQty(0d); combineSo.setCompleteQty(0d); for
			 * (SPartTask subBatch : combinePartTask.getCombinedBatchs()) {
			 * SOperationTask subSo = subBatch.getByIddesc(combineSo
			 * .getOperationIdDesc()); if (subSo != null) {
			 * combineSo.setPlanQty(combineSo.getPlanQty() +
			 * subSo.getPlanQty());
			 * combineSo.setCompleteQty(combineSo.getCompleteQty() +
			 * subSo.getCompleteQty()); } } if (combineSo.getPlanQty()==0 ||
			 * combineSo.getCompleteQty() >= combineSo.getPlanQty()) {
			 * removedCombineOperationList.add(combineSo); } else {
			 * combineSo.calTaskWork(); } }
			 * 
			 * for (SOperationTask combineSo : removedCombineOperationList) { //
			 * 移除一个节点的方法 try {
			 * scheduleOperationTaskManager.removeOperationTask(combineSo); }
			 * catch (Exception e) { // TODO Auto-generated catch block
			 * e.printStackTrace(); } }
			 * 
			 * 
			 * if(combinePartTask.getOperationTaskList().size()==0)
			 * this.removePartTask(combinePartTask);
			 */

		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

	}

	/*
	 * 零件任务完成， 暂时先用移除，移除该成组任务的同时，移除工序任务，子任务
	 */
	public void completePartTask(SPartTask partTask) throws Exception {
		// 将其子任务也设置为已经完成
		// 这个逻辑也还设计的不错
		List<SPartTask> subList = partTask.getCombinedBatchs();
		if (subList != null && subList.size() > 0) {
			for (SPartTask subTask : partTask.getCombinedBatchs()) {
				completePartTask(subTask);
			}
		}
		// 临时
		// todo
		// 如果外面的任务还未完成，先将其设置成已经完成
		if (partTask.getTaskScheduleType() == SPartTask.TASKSCHEDULETYPE_NORMAL) {
			scheduleTaskDao.removeCompletedPartTak(partTask.getTaskUid());
		}
		this.removePartTask(partTask, false);

		// List<SOperationTask> ops = new ArrayList<SOperationTask>();
		// for (SOperationTask so : partTask.getOperationTaskList()) {
		// ops.add(so);
		//
		// }
		// for (SOperationTask so : ops) {
		// scheduleOperationTaskManager.removeOperationTask(so);
		// }
		// scheme.getAllPartTaskMap().remove(partTask.getTaskUid());
		//
		//
		//
		// ops = null;

	}

	public void removeAllOp(SPartTask partTask) throws Exception {
		List<SOperationTask> ops = new ArrayList<SOperationTask>();
		for (SOperationTask so : partTask.getOperationTaskList()) {
			ops.add(so);

		}
		for (SOperationTask so : ops) {
			scheduleOperationTaskManager.removeOperationTask(so, true);
		}
	}

	@Transactional
	public void deletePartTask(SPartTask partTask) throws Exception {
		// TODO Auto-generated method stub
		// 先取消任务才能删除，否则可能会出现在排产集，待排产集都找不到任务的bug
		// 因为taskschedulestate=-1
		// lqm todo
		// 以后应该将这个提示直接放在前端
		// 2014-12/0
		// if (partTask.getTaskScheduleType() ==
		// SPartTask.TASKSCHEDULETYPE_COMBINEBATCH)
		// throw new
		// Exception("零件任务:"+partTask.toFriendlyString()+"为一个合批任务,只能执行<取消合批>操作！");
		//					
		//		

		ScheduleScheme scheme = partTask.getScheme();
		// 取得本任务的合批任务
		SPartTask scp = getCombineBatch(partTask);
		if (scp != null) {
			this.removeBatchFromCombinedBatch(scheme, scp.getTaskUid(),
					partTask.getBatchNum());
		}

		List<SOperationTask> ops = new ArrayList<SOperationTask>();
		for (SOperationTask so : partTask.getOperationTaskList()) {
			ops.add(so);

		}
		for (SOperationTask so : ops) {
			scheduleOperationTaskManager.removeOperationTask(so, true);
		}

		if (scheme.getSchedulePartTasks().contains(partTask))
			scheme.getSchedulePartTasks().remove(partTask);

		scheme.getAllPartTaskMap().remove(partTask.getTaskUid());

		// by zy
		this.delete(partTask);

		// 删除link
		// lqm todo

		DemandSTaskLinkManager demandSTaskLinkManager = SpringUtils
				.getBean("demandSTaskLinkManager");

		demandSTaskLinkManager.deleteLinksByTaskUid(partTask.getScheduleUid(),
				partTask.getTaskUid());

		ops = null;

	}

	@Transactional
	public void removePartTask(SPartTask partTask, Boolean iSRemoveFromDB)
			throws Exception {
		// TODO Auto-generated method stub
		// 先取消任务才能删除，否则可能会出现在排产集，待排产集都找不到任务的bug
		// 因为taskschedulestate=-1
		// lqm todo
		// 以后应该将这个提示直接放在前端
		// 2014-12/0
		// if (partTask.getTaskScheduleType() ==
		// SPartTask.TASKSCHEDULETYPE_COMBINEBATCH)
		// throw new
		// Exception("零件任务:"+partTask.toFriendlyString()+"为一个合批任务,只能执行<取消合批>操作！");
		//					
		//		
		if (partTask == null) {
			return;
		}
		ScheduleScheme scheme = partTask.getScheme();
		// 取得本任务的合批任务
		SPartTask scp = getCombineBatch(partTask);
		if (scp != null) {
			this.removeBatchFromCombinedBatch(scheme, scp.getTaskUid(),
					partTask.getBatchNum());
		}

		List<SOperationTask> ops = new ArrayList<SOperationTask>();
		for (SOperationTask so : partTask.getOperationTaskList()) {
			ops.add(so);

		}
		// 根据是否删除零件任务决定是否从数据库中删除工序任务 hba
		for (SOperationTask so : ops) {
			scheduleOperationTaskManager
					.removeOperationTask(so, iSRemoveFromDB);
		}

		if (scheme.getSchedulePartTasks().contains(partTask))
			scheme.getSchedulePartTasks().remove(partTask);

		if (iSRemoveFromDB) {
			this.delete(partTask);
			scheme.getAllPartTaskMap().remove(partTask.getTaskUid());
			// 删除link
			DemandSTaskLinkManager demandSTaskLinkManager = SpringUtils
					.getBean("demandSTaskLinkManager");

			demandSTaskLinkManager.deleteLinksByTaskUid(partTask
					.getScheduleUid(), partTask.getTaskUid());
		} else {
			// by hba
			// 设置零件任务的实际完成
			partTask.setActualFinish(new Date());
			partTask.setTaskState(SPartTask.TASKSTATE_COMPLETED);
			partTask.setCompleteQty(partTask.getPlanQty());
			partTask.setTaskScheduleState(SPartTask.TASKSCHEDULESTATE_NO);
			// partTask.set
			this.update(partTask);
			// 设置零件任务对应的订单的完成数量(如果一个批次对应多个订单，则订单按照交货期升序排列)
			List<DemandSTaskLink> demandSTaskList = demandSTaskLinkManager
					.getEffectedLinksByTaskUid(scheme.getScheduleUid(),
							partTask.getTaskUid());
			if (demandSTaskList != null && demandSTaskList.size() > 0) {
				for (DemandSTaskLink demandSTaskLink : demandSTaskList) {
					String demandUid = demandSTaskLink.getDemandUid();
					Demand demand = demandDao.getById(demandUid);
					if (demand != null) {
						demand.setDeliveryQty(demand.getDeliveryQty()
								+ demandSTaskLink.getLinkQty().floatValue());
						if (demand.getDeliveryQty() >= demand.getDueQty()) {
							// 将零件任务的实际完成作为订单的实际完成 hba
							demand.setActualFinish(partTask.getActualFinish());
//							demand.setDemandState((long)Demand.DEMANDSTATE_FINISHED);
						}
						demandDao.update(demand);
					}
					demandSTaskLink.setIsInEffect(0);
					demandSTaskLinkManager.saveOrUpdateLink(demandSTaskLink);
				}
			}
		}

		// this.delete(partTask);
		// hba

		// lqm todo

		ops = null;

	}

	 //改变Boolean为Void
	public void add(Serializable object) throws Exception {
		// TODO Auto-generated method stub
		 super.add(object);
	}

	 
	public Boolean delete(Serializable object) throws Exception {
		SPartTask sp = (SPartTask) object;
		try {
			SPartTask persistensePartTask = this.schedulePartTaskDao
					.getSchedulePartTask(sp.getScheduleUid(), sp.getTaskUid());

			if (persistensePartTask != null) {
				super.delete(persistensePartTask);
			}
		} catch (BaseDBException e) {

			throw new BaseBusinessException(e.getMessage());
		}

		return true;
	}

	@Transactional
	public void addPartTask(ScheduleScheme scheme, SPartTask partTask)
			throws Exception {
		SPartTask newPartTask = new SPartTask();
		if (partTask.getPartUid() == null || partTask.getBatchNum() == null)
			throw new Exception("请输入完整的零件任务信息");

		ObjectOperation.copyAttributes(partTask, newPartTask);

		// added by hba to modify the plangrade
		Map partTaskMap = scheme.getAllPartTaskMap();
		Iterator it = partTaskMap.keySet().iterator();
		String drawingId = partTask.getDrawingId();
		int planGrade = partTask.getPlanGrade();
		while (it.hasNext()) {
			String key = it.next().toString();
			SPartTask nextPartTask = (SPartTask) partTaskMap.get(key);
			System.out.println(nextPartTask.getDrawingId());
			if (nextPartTask.getDrawingId().equals(drawingId)) {
				nextPartTask.setPlanGrade(planGrade);
				System.out
						.println("-------------*******************sfsfsdgf1213323232423423423452352523532555555555555555555555555555555555sdgfsgf");
				partTaskMap.put(key, nextPartTask);
			}
		}

		newPartTask.setScheme(scheme);
		newPartTask.setTaskUid(IdentityGenerator.GetIdentityString());
		newPartTask.setDeptUid(scheme.getDeptUid());
		if (newPartTask.getTaskState() == null)
			newPartTask.setTaskState(101);

		// newPartTask.setOperationTaskList(new ArrayList<SOperationTask>());
		scheme.getAllPartTaskMap().put(newPartTask.getTaskUid(), newPartTask);

		// 这个地方应该改为小于104都要应用工艺
		if (newPartTask.getTaskState() < 104) {
			Routing planRouting = this.scheduleRoutingManager
					.getDefaultRouting(partTask.getPartUid());
			if (planRouting != null) {
				this.applyRouting(scheme, newPartTask, planRouting, null);
				// 更新零件当前使用的工艺
				newPartTask.setRouting(planRouting.getRoutingUid());
			}
			// this.applyRouting(scheduleUid, partTaskUid, routingUid,
			// currentOperationIdDesc)
		}
		// 先设置成等待状态再置位入调度
		newPartTask.setTaskScheduleState(SPartTask.TASKSCHEDULESTATE_WAITING);

		this.intoSchedule(newPartTask);
		// newPartTask.setControlFinish(newPartTask.getLateFinish());
		// this.calcSlack(newPartTask)

		this.add(newPartTask);

	}

	@Transactional
	public void savePartTask(ScheduleScheme scheme, List<SPartTask> partTaskList)
			throws Exception {
		for (SPartTask partTask : partTaskList) {
			if (partTask.getObjectState() == BasicModel.OBJECTSTATE_TOBEUPDATED) {
				SPartTask oldPartTask = scheme.getAllPartTaskMap().get(
						partTask.getTaskUid());
				if (oldPartTask == null)
					throw new Exception("找不到更新的零件任务！" + oldPartTask);
				// 写日志
				// 旧的信息
				Element taskElement = new Element("PARTTASK_PLANINFO");
				taskElement.setAttribute("partUid", oldPartTask.getPartUid());
				taskElement.setAttribute("taskUid", oldPartTask.getTaskUid());
				taskElement.setAttribute("drawingId", oldPartTask
						.getDrawingId());
				taskElement.setAttribute("partName", oldPartTask.getPartName());
				taskElement.setAttribute("batchNum", oldPartTask.getBatchNum());

				SimpleDateFormat formatDate = new SimpleDateFormat(
						"yyyy-MM-dd HH:mm:ss");
				if (oldPartTask.getEarlyStart() == null) {
					taskElement.setAttribute("earlyStart", "");
				} else {
					taskElement.setAttribute("earlyStart", formatDate
							.format(oldPartTask.getEarlyStart()));
				}
				if (oldPartTask.getLateFinish() == null) {
					taskElement.setAttribute("lateFinish", "");
				} else {
					taskElement.setAttribute("lateFinish", formatDate
							.format(oldPartTask.getLateFinish()));
				}
				taskElement.setAttribute("planQty", String.valueOf(oldPartTask
						.getPlanQty()));
				taskElement.setAttribute("isCritical", String
						.valueOf(oldPartTask.getIsCritical()));
				taskElement.setAttribute("delayCost", String
						.valueOf(oldPartTask.getDelayCost()));
				taskElement.setAttribute("planGrade", String
						.valueOf(oldPartTask.getPlanGrade()));

				updatePartTask(scheme, partTask);

				// 新信息

				Element newTaskElement = new Element("newPlanInfo");
				newTaskElement.setAttribute("partUid", partTask.getPartUid());
				newTaskElement.setAttribute("taskUid", partTask.getTaskUid());
				newTaskElement.setAttribute("drawingId", partTask
						.getDrawingId());
				newTaskElement.setAttribute("partName", partTask.getPartName());
				newTaskElement.setAttribute("batchNum", partTask.getBatchNum());

				if (partTask.getEarlyStart() == null) {
					newTaskElement.setAttribute("earlyStart", "");
				} else {
					newTaskElement.setAttribute("earlyStart", formatDate
							.format(partTask.getEarlyStart()));
				}
				if (partTask.getLateFinish() == null) {
					newTaskElement.setAttribute("lateFinish", "");
				} else {
					newTaskElement.setAttribute("lateFinish", formatDate
							.format(partTask.getLateFinish()));
				}
				newTaskElement.setAttribute("planQty", String.valueOf(partTask
						.getPlanQty()));
				newTaskElement.setAttribute("isCritical", String
						.valueOf(partTask.getIsCritical()));
				newTaskElement.setAttribute("delayCost", String
						.valueOf(partTask.getDelayCost()));
				newTaskElement.setAttribute("planGrade", String
						.valueOf(partTask.getPlanGrade()));

				taskElement.addContent(newTaskElement);

				this.scheduleOperationRecordManager.writeOperationPartTaskLog(
						scheme, oldPartTask, partTask,
						ScheduleEvent.EVENTTYPE_PARTTASK_PLANINFO);

				this.scheduleEventManager.writeOperLog(scheme,
						ScheduleEvent.EVENTTYPE_PARTTASK_PLANINFO, taskElement);

				updatePartNumber(partTask);
			} else if (partTask.getObjectState() == BasicModel.OBJECTSTATE_TOBEDELETED) {
				removePartTask(scheme.getAllPartTaskMap().get(
						partTask.getTaskUid()), true);
				// 写日志
				Element taskElement = new Element("PARTTASK_DELETE");
				taskElement.setAttribute("taskUid", partTask.getTaskUid());
				taskElement.setAttribute("partUid", partTask.getPartUid());
				taskElement.setAttribute("drawingId", partTask.getDrawingId());
				taskElement.setAttribute("partName", partTask.getPartName());
				taskElement.setAttribute("batchNum", partTask.getBatchNum());

				taskElement.setAttribute("planQty", String.valueOf(partTask
						.getPlanQty()));
				taskElement.setAttribute("isCritical", String.valueOf(partTask
						.getIsCritical()));
				taskElement.setAttribute("delayCost", String.valueOf(partTask
						.getDelayCost()));
				taskElement.setAttribute("planGrade", String.valueOf(partTask
						.getPlanGrade()));

				SimpleDateFormat formatDate = new SimpleDateFormat(
						"yyyy-MM-dd HH:mm:ss");
				if (partTask.getEarlyStart() == null) {
					taskElement.setAttribute("earlyStart", "");
				} else {
					taskElement.setAttribute("earlyStart", formatDate
							.format(partTask.getEarlyStart()));
				}
				if (partTask.getLateFinish() == null) {
					taskElement.setAttribute("lateFinish", "");
				} else {
					taskElement.setAttribute("lateFinish", formatDate
							.format(partTask.getLateFinish()));
				}
				this.scheduleOperationRecordManager.writeOperationPartTaskLog(
						scheme, partTask, partTask,
						ScheduleEvent.EVENTTYPE_PARTTASK_DELETE);

				this.scheduleEventManager.writeOperLog(partTask.getScheme(),
						ScheduleEvent.EVENTTYPE_PARTTASK_DELETE, taskElement);
			} else if (partTask.getObjectState() == BasicModel.OBJECTSTATE_TOBEADDED) {
				addPartTask(scheme, partTask);
				// 用于更新颜色
				scheme.initColorMap();
				// 写日志
				Element taskElement = new Element("PARTTASK_ADD");
				// taskElement.setAttribute("taskUid", partTask.getTaskUid());
				taskElement.setAttribute("partUid", partTask.getPartUid());
				taskElement.setAttribute("drawingId", partTask.getDrawingId());
				taskElement.setAttribute("partName", partTask.getPartName());
				taskElement.setAttribute("batchNum", partTask.getBatchNum());
				if (partTask.getModel() != null) {
					taskElement.setAttribute("model", partTask.getModel());
				} else {
					taskElement.setAttribute("model", "");
				}

				taskElement.setAttribute("planQty", String.valueOf(partTask
						.getPlanQty()));
				taskElement.setAttribute("isCritical", String.valueOf(partTask
						.getIsCritical()));
				taskElement.setAttribute("delayCost", String.valueOf(partTask
						.getDelayCost()));
				taskElement.setAttribute("planGrade", String.valueOf(partTask
						.getPlanGrade()));

				SimpleDateFormat formatDate = new SimpleDateFormat(
						"yyyy-MM-dd HH:mm:ss");
				if (partTask.getEarlyStart() == null) {
					taskElement.setAttribute("earlyStart", "");
				} else {
					taskElement.setAttribute("earlyStart", formatDate
							.format(partTask.getEarlyStart()));
				}
				if (partTask.getLateFinish() == null) {
					taskElement.setAttribute("lateFinish", "");
				} else {
					taskElement.setAttribute("lateFinish", formatDate
							.format(partTask.getLateFinish()));
				}

				this.scheduleOperationRecordManager.writeOperationPartTaskLog(
						scheme, partTask, partTask,
						ScheduleEvent.EVENTTYPE_PARTTASK_ADD);

				this.scheduleEventManager.writeOperLog(partTask.getScheme(),
						ScheduleEvent.EVENTTYPE_PARTTASK_ADD, taskElement);
				updatePartNumber(partTask);

			}

		}

	}

	/**
	 * update plangrade in b_part_number with that in schedule_part_task
	 * 
	 * @param partTask
	 *            by hba 2015-11-17
	 * @throws Exception 
	 */
	public void updatePartNumber(SPartTask partTask) throws Exception {

		// TODO Auto-generated method stub
		List<Part> partlist = null;
//		partlist = this.partDao.getPartsByDrawingId(partTask.getDrawingId());
		if (partlist != null) {
			for (Part part : partlist) {
				part.setPlanGrade(partTask.getPlanGrade().toString());
			}
			this.partManager.update(partlist);
		}

	}

	public PartDao getPartDao() {
		return partDao;
	}

	public void setPartDao(PartDao partDao) {
		this.partDao = partDao;
	}

	public PartManager getPartManager() {
		return partManager;
	}

	public void setPartManager(PartManager partManager) {
		this.partManager = partManager;
	}

	 
	public Set<PartTask> getOPartTasks(SPartTask partTask) throws Exception {
		PartTask oo;
		Set<PartTask> ooTaskSet = new HashSet<PartTask>();
		if (partTask.getTaskScheduleType().equals(
				SPartTask.TASKSCHEDULETYPE_COMBINEBATCH)) {
			for (SPartTask childPartTask : partTask.getCombinedBatchs()) {
				oo = this.getOPartTask(childPartTask);
				if (oo != null)
					ooTaskSet.add(oo);
			}
			return ooTaskSet;
		}

		oo = this.getOPartTask(partTask);
		if (oo != null)
			ooTaskSet.add(oo);
		return ooTaskSet;

	}

	 
	public PartTask getOPartTask(SPartTask partTask) throws Exception {
		PartTask op = null;
		// try {
		op = (PartTask) this.partTaskDao.getById(partTask.getTaskUid());
		if (op == null)// 隐患，partuid,batchnum不能唯一决定
			op = this.partTaskDao.getPartTaskByPartUidAndBatchNum(partTask
					.getPartUid(), partTask.getBatchNum(), partTask
					.getMasterShopUid());
		// } catch (BaseDBException e) {
		// // TODO Auto-generated catch block
		// e.printStackTrace();
		// }

		return op;
	}

	@Transactional
	public void updatePartTask(ScheduleScheme scheme, SPartTask partTask)
			throws Exception {
		// TODO Auto-generated method stub
		SPartTask originPartTask = scheme.getAllPartTaskMap().get(
				partTask.getTaskUid());
		Map partTaskMap = scheme.getAllPartTaskMap();
		Iterator it = partTaskMap.keySet().iterator();
		String drawingId = partTask.getDrawingId();
		int planGrade = partTask.getPlanGrade();
		System.out.println("-------------*******************sfsfsdgfsdgfsgf"
				+ "-----" + partTaskMap.keySet().size() + "-----" + drawingId);
		while (it.hasNext()) {
			String key = it.next().toString();
			SPartTask nextPartTask = (SPartTask) partTaskMap.get(key);
			System.out.println(nextPartTask.getDrawingId());
			if (nextPartTask.getDrawingId().equals(drawingId)) {
				nextPartTask.setPlanGrade(planGrade);
				System.out
						.println("-------------*******************sfsfsdgf1213323232423423423452352523532555555555555555555555555555555555sdgfsgf");
				partTaskMap.put(key, nextPartTask);
			}
		}

		if (originPartTask == null)
			throw new Exception("找不到对应的零件任务");
		ObjectOperation.copyAttributes(partTask, originPartTask);
		// 置空不行，所以要补上这句话
		// lqm todo
		originPartTask.setIsCritical(partTask.getIsCritical());
		// todo
		// null值的copy问题
		if (partTask.getLateFinish() == null)
			originPartTask.setLateFinish(null);
		if (partTask.getNotes() == null)
			originPartTask.setNotes(null);
		if (partTask.getActualStart() == null) {
			originPartTask.setActualStart(null);
		}
		if (partTask.getActualFinish() == null) {
			originPartTask.setActualFinish(null);
		}

		if (partTask.getTaskState() != null
				&& partTask.getTaskState().equals(106))
			this.completePartTask(originPartTask);

		// 同步交货期和关键等级设置
		// syncLAndC(originPartTask);
		// originPartTask.setControlFinish(originPartTask.getLateFinish());
		// this.calcSlack(originPartTask);

		// 存储到数据库
		this.update(originPartTask);
		// 更新原来的零件任务

		try {
			Set<PartTask> ps = getOPartTasks(partTask);
			if (ps != null && ps.size() > 0) {
				for (PartTask p : ps) {
					p.setLateFinish(partTask.getLateFinish());
//					p.setIsCritical((long)partTask.getIsCritical());
					// 对持久性对象更新时，在一个事务中取后马上赋值，
					// hibernate会自动update
					// this.partTaskManager.update(p);
				}

			}
			Routing planRouting = this.scheduleRoutingManager
					.getDefaultRouting(partTask.getPartUid());

			// added by hba 用于通过设置当前工序就能完成进度更新的功能
			String currentIdString = partTask.getCurrentOperationIdString();
			boolean needDelete = false;
			List<SOperationTask> deleteList = new ArrayList<SOperationTask>();
			if (currentIdString != null && !currentIdString.equals("")) {
				for (SOperationTask opTask : originPartTask
						.getOperationTaskList()) {
					if (currentIdString.equals(opTask.getOperationIdDesc())) {
						needDelete = true;
						break;
					}
					deleteList.add(opTask);
				}
			}
			if (needDelete) {
				for (SOperationTask opTask : deleteList) {
					scheduleOperationTaskManager.removeOperationTask(opTask,
							false);
				}
			}

			// added by hba to solve operation task number not updated
			// String currentOperationIdDesc = this.getCurrentOperationIdDesc(
			// scheme, originPartTask);
			// if (planRouting != null)
			// this.applyRouting(scheme, originPartTask, planRouting,
			// currentOperationIdDesc);

			// this.update(partTask);

			// lqm
			// 千万注意spartTask并不是持久对象啊
			//
			// SPartTask psp = (SPartTask) this.schedulePartTaskDao
			// .getSchedulePartTask(spartTask.getScheduleUid(), spartTask
			// .getTaskUid());
			// if (psp != null) {
			// psp.setLateFinish(spartTask.getLateFinish());
			// psp.setIsCritical(spartTask.getIsCritical());
			// // this.update(spartTask);
			// }

		} catch (Exception e) {// 不让抛出任何异常
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

	}

	 
	public Boolean update(Serializable object) throws Exception {
		try {
			SPartTask sPartTask = (SPartTask) object;
			//有问题 2017/5/10
			SPartTask persistensePartTask = this.schedulePartTaskDao
					.getSchedulePartTask(sPartTask.getScheduleUid(), sPartTask
							.getTaskUid());
			if (persistensePartTask != null) {
				ObjectOperation.copyAttributes(sPartTask, persistensePartTask,
						true);
				super.update(persistensePartTask);
			}
		} catch (BaseDBException e) {
			e.printStackTrace();
		} catch (RuntimeException e) {
			e.printStackTrace();
		}
		return true;
	}

	// 同步交货期和关键等级设置,临时用
	@Transactional
	private void syncLAndC(SPartTask spartTask) {
		try {
			Set<PartTask> ps = getOPartTasks(spartTask);
			if (ps != null && ps.size() > 0) {
				for (PartTask p : ps) {
					p.setLateFinish(spartTask.getLateFinish());
//					p.setIsCritical(spartTask.getIsCritical().longValue());
					// 在一个事务中取后马上赋值，
					// hibernate会自动update
					// this.partTaskManager.update(p);
				}

			}
			// lqm
			// 千万注意spartTask并不是持久对象啊

			SPartTask psp = (SPartTask) this.schedulePartTaskDao
					.getSchedulePartTask(spartTask.getScheduleUid(), spartTask
							.getTaskUid());
			if (psp != null) {
				psp.setLateFinish(spartTask.getLateFinish());
				psp.setIsCritical(spartTask.getIsCritical());
				// this.update(spartTask);
			}
		} catch (Exception e) {// 不让抛出任何异常
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	public String getNetChartXml(ScheduleScheme scheme, String partTaskUid)
			throws Exception {
		SPartTask partTask = scheme.getAllPartTaskMap().get(partTaskUid);
		if (partTask == null)
			throw new Exception("无法找到对应零件任务：" + partTaskUid);
		// 声明AppData节点与xml文档

		Element appData = new Element("graph");
		appData.setAttribute("name", "调度任务网络图");
		appData.setAttribute("layout", "flow_horizontal");
		Document doc = new Document(appData);
		// doc.setDocType(docType);

		// 声明comlpexType节点
		Element nodes = new Element("nodes");
		appData.addContent(nodes);
		Element links = new Element("links");
		appData.addContent(links);

		SimpleDateFormat formatDate = new SimpleDateFormat("M月d日");
		for (SOperationTask so : partTask.getOperationTaskList()) {
			Element node = new Element("node");
			node.setAttribute("dbUniqueID", so.getTaskUid());
			node.setAttribute("operationName", so.getTaskName());
			node.setAttribute("operationIdDesc", so.getOperationIdDesc());
			if (so.getPlanStart() != null)
				node.setAttribute("planStart", formatDate.format(so
						.getPlanStart()));
			if (so.getPlanFinish() != null)
				node.setAttribute("planFinish", formatDate.format(so
						.getPlanFinish()));
			if (so.getDevice() != null)
				node.setAttribute("deviceName", so.getDevice().getDeviceName());
			node.setAttribute("x", "0");
			node.setAttribute("y", "0");
			node.setAttribute("class", "mmNodeScheduleTask");
			nodes.addContent(node);

			for (SOperationLink sl : so.getPredLinkSet()) {
				Element link = new Element("link");

				link.setAttribute("from", sl.getPredecessorUid());
				link.setAttribute("to", sl.getSuccessorUid());
				link.setAttribute("dbUniqueID", sl.getLinkUid());
				link.setAttribute("class", "mmLinkScheduleTask");
				links.addContent(link);
				link = null;
			}
			node = null;
		}

		nodes = null;

		links = null;
		appData = null;

		// 声明Data节点

		Format format = Format.getCompactFormat();

		format.setEncoding("UTF-8");
		format.setIndent("  ");
		XMLOutputter outputter = new XMLOutputter(format);
		if (log.isDebugEnabled()) {
			log.debug(outputter.outputString(doc));
		}
		return outputter.outputString(doc);

		// String xml=
		//
		// "<nodes>\n" +
		// "<node x='12' y='23' class='mmNodeScheduleTask' dbUniqueID='123'
		// operationName='开始' OperationIdDesc='10'/>\n" +
		// "<node x='120' y='230' class='mmNodeEnd' dbUniqueID='1345'/>\n" +
		// "<node x='220' y='130' class='mmNodeStart' dbUniqueID='1346'/>\n" +
		// "</nodes>\n" +
		// "<links>\n" +
		// "<link from='123' to='1345' class='mmLinkScheduleTask'
		// dbUniqueID='1233' att1='11' att2='22'/>\n" +
		// "<link from='1346' to='123' class='mmLinkScheduleTask'
		// dbUniqueID='1237' att1='33' att2='444'/>\n" +
		// "</links>\n" +
		// "</graph>";

		// return xml;

	}

	public void setScheduleLinkManager(ScheduleLinkManager scheduleLinkManager) {
		this.scheduleLinkManager = scheduleLinkManager;
	}

	 
	public void backToRouting(String scheduleUid, String partTaskUid)
			throws Exception {
		ScheduleScheme scheme = ScheduleUtils.getScheduleScheme(scheduleUid);
		SPartTask partTask = scheme.getAllPartTaskMap().get(partTaskUid);
		String routinString = partTask.getRouting();
		List<Routing> routingList = routingDao.findByProperty("routingUid",
				routinString);
		if (routinString == null || routinString.equals("")) {
			throw new Exception("零件任务没有工艺记录！" + partTask.toFriendlyString());
		}
		List<SOperationTask> opTaskList = partTask.getOperationTaskList();

		if (opTaskList != null && opTaskList.size() > 0) {
			for (SOperationTask operationTask : opTaskList) {
				if (operationTask.getOpUid() == null) {
					operationTask.setOpUid(IdentityGenerator.GetIdentityLong()
							+ "");
					scheduleOperationTaskManager.update(operationTask);
				}
				Operation operation = (Operation) operationDao
						.getById(operationTask.getOpUid());
				if (operation == null) {
					// 如果没有则说明是新建的，也要添加到基础工艺中，关键是如何获取当前使用的哪个版本的工艺呢？
					Operation o = new Operation();
//					o.setTransferBatchQty(operationTask.getTransferBatchQty());
//					o.setProcessBatchQty(operationTask.getProcessBatchQty());
//					o.setProcessBatchRunTime(operationTask
//							.getProcessBatchRunTime());
					o.setUniqueId(operationTask.getOpUid());
					o.setUuid(operationTask.getOpUid());
//					o.setOperationId(operationTask.getOperationId().doubleValue());
					o.setOperationName(operationTask.getTaskName());
					o.setOperationIdDesc(operationTask.getOperationIdDesc());
//					if (operationTask.getEstiPreTime() != null)
//						o.setEstiPostOpTime(operationTask.getEstiPreTime());
//					if (operationTask.getEstiRunTime() != null)
//						o.setEstiRunTime(operationTask.getEstiRunTime());
//					if (operationTask.getEstiDelayTime() != null)
//						o.setEstiDelayTime(operationTask.getEstiDelayTime());
					if (operationTask.getWorkCenterUid() == null
							|| operationTask.getWorkCenterUid().equals(
									"cooperationCenter")) {
						o.setWorkCenterUid(null);
					} else {
						o.setWorkCenterUid(operationTask.getWorkCenterUid());
					}
//					o.setRoutingUid(routinString);
					o.setDeptUid(operationTask.getMasterShop());
					operationManager.add(o);

					continue;
				}
				// 同一事务中，hibernate自己直接发sql
//				operation.setEstiPostOpTime(operationTask.getEstiPreTime());
//				operation.setEstiRunTime(operationTask.getEstiRunTime());
//				operation.setEstiDelayTime(operationTask.getEstiDelayTime());
//				operation.setOperationId(operationTask.getOperationId().doubleValue());
				if (operationTask.getSWorkCenterUid() != null
						&& !(operationTask.getSWorkCenter().getIsVirtual()))
					operation.setWorkCenterUid(operationTask
							.getSWorkCenterUid());
				if (operationTask.getMasterShop() != null)
					operation.setDeptUid(operationTask.getMasterShop());
				operationManager.update(operation);

			}

		}

	}

	 
	public void newRouting(String scheduleUid, String taskUid,
			String versionId, String routingName, String productPhase,
			String routingType, boolean IsDefault) throws Exception {
		ScheduleScheme scheme = scheduleSchemeManager.getScheduleScheme(scheduleUid);
		SPartTask partTask = scheme.getAllPartTaskMap().get(taskUid);
		Routing routine = new Routing();
		String routingUid = IdentityGenerator.GetIdentityString();
		routine.setRoutingUid(routingUid);
		routine.setCreatorUid(scheme.getCreatorUid());
		routine.setVersionId(versionId);
		routine.setRoutingName(routingName);
		routine.setProductPhase(productPhase);
		routine.setIsEffective(true);
		routine.setCreateTime(new Date());
		routine.setPartUid(partTask.getPartUid());
//		routine.setUseEffective(1l);
		routine.setMasterShopUid(scheme.getDeptUid());
		routine.setRoutingType(routingType);
		routine.setCheckerUid(scheme.getCreatorUid());
		routine.setRoutingManagerUid(scheme.getCreatorUid());
		routingManager.add(routine);

		if (IsDefault) {
//			routingManager.setDefaultPlanRouting(routingUid);
		}

		partTask.setRouting(routingUid);
		this.update(partTask);
		List<SOperationTask> opTaskList = partTask.getOperationTaskList();
		float operationId = 0;
		if (opTaskList != null && opTaskList.size() > 0) {
			for (SOperationTask operationTask : opTaskList) {
				Operation o = new Operation();
//				o.setTransferBatchQty(operationTask.getTransferBatchQty());
//				o.setProcessBatchQty(operationTask.getProcessBatchQty());
//				o
//						.setProcessBatchRunTime(operationTask
//								.getProcessBatchRunTime());
//				o.setUniqueId(Long.toString(IdentityGenerator
//						.GetIdentityLong()));
//				o.setOperationId((double)operationId++);
				o.setOperationName(operationTask.getTaskName());
				o.setOperationIdDesc(operationTask.getOperationIdDesc());
//				if (operationTask.getEstiPreTime() != null)
//					o.setEstiPostOpTime(operationTask.getEstiPreTime());
//				if (operationTask.getEstiRunTime() != null)
//					o.setEstiRunTime(operationTask.getEstiRunTime());
//				if (operationTask.getEstiDelayTime() != null)
//					o.setEstiDelayTime(operationTask.getEstiDelayTime());
//				if (operationTask.getWorkCenterUid() == null
//						|| operationTask.getWorkCenterUid().equals(
//								"cooperationCenter")) {
//					o.setWorkCenterUid(null);
//				} else {
//					o.setWorkCenterUid(operationTask.getWorkCenterUid());
//				}
//				o.setRoutingUid(routine.getRoutingUid());
//				o.setDeptUid(operationTask.getMasterShop());
				operationManager.add(o);
			}
		}
	}

	 
	public void backToMasterScheduleRouting(String masterScheduleUid,
			SOperationTask masterOperationTask) throws Exception {
		String deptName = null;
//		if (SysUtil.getSessionDeptId() != null
//				|| SysUtil.getSessionDeptId() != "") {
//			Dept dept = (Dept) deptDao.getById(SysUtil.getSessionDeptId());
//			deptName = dept.getDeptName();
//		}

		if (masterOperationTask.getOpUid() != null) {

			Operation operation = (Operation) operationDao
					.getById(masterOperationTask.getOpUid());

			if (operation != null) {

				// 同一事务中，hibernate自己直接发sql
//				operation
//						.setEstiPostOpTime(masterOperationTask.getEstiPreTime());
//				operation.setEstiRunTime(masterOperationTask.getEstiRunTime());
//				// operation.setEstiDelayTime(masterOperationTask.getEstiDelayTime());
//				operation.setNotes(deptName + "协作工段修改");
//				operation.setIsSpecial(true); // 协作工段定义工时
				operationManager.update(operation);
			}

		}

	}

	@Transactional
	 
	public void applyRouting(String scheduleUid, String partTaskUid,
			String routingUid, String currentOperationIdDesc) throws Exception {
		ScheduleScheme scheme = ScheduleUtils.getScheduleScheme(scheduleUid);
		SPartTask partTask = scheme.getAllPartTaskMap().get(partTaskUid);
		Integer taskState = partTask.getTaskState();
		Routing routing = (Routing) routingDao.getById(routingUid);
		if (routing == null)
			throw new Exception("无法找到对应工艺路线" + routingUid);

		this.applyRouting(scheme, partTask, routing, currentOperationIdDesc);
		// 应用工艺时记录下来by hba
		partTask.setRouting(routing.getRoutingUid());
		// 恢复应用工艺前的状态 hba
		partTask.setTaskState(taskState);
		this.update(partTask);
	}

	private static boolean isOperationEqual(String combineOperationIddesc,
			String OperationIddesc) {
		boolean operationEqual = false;
		if (combineOperationIddesc == null || OperationIddesc == null)
			return false;
		// 处理外面的工序也可能含有斜杆的情况
		if (combineOperationIddesc.equals(OperationIddesc))
			return true;

		String[] strOperations = combineOperationIddesc.split("/");
		for (int i = 0; i < strOperations.length; i++) {
			if (strOperations[i].equals(OperationIddesc))
				return true;
		}
		return false;

	}

	@Transactional
	 
	public void applyRouting(ScheduleScheme scheme, SPartTask partTask,
			Routing routing, String currentOperationIdDesc) throws Exception {

		// 保存当前工序状态和数量
		Map<String, SOperationTask> oldStateMap = new HashMap<String, SOperationTask>();
		for (SOperationTask so : partTask.getOperationTaskList()) {
			// if(so.getTaskScheduleState()>205)
			oldStateMap.put(so.getOperationIdDesc(), so);
		}

		// 先移除所有工序任务
		removeAllOp(partTask);
		if (routing == null)
			throw new Exception("分解任务时找不到有效工艺路线！");

		List<SOperationTask> opTaskList = partTask.getOperationTaskList();
		List<Operation> opList = routing.getOperations();
		// List<Operation> opList=this.routingManager

		if (opList != null && opList.size() > 0) {

			int iCur = 0;
			if (currentOperationIdDesc != null) {
				for (int i = 0; i < opList.size(); i++) {
					Operation operation = opList.get(i);
					if (isOperationEqual(operation.getOperationIdDesc(),
							currentOperationIdDesc)) {
						iCur = i;
						break;
					}
				}
			}

			for (int i = iCur; i < opList.size(); i++) {
				Operation operation = opList.get(i);

				SOperationTask newOpTask = new SOperationTask();

				// 转运批量
//				newOpTask.setTransferBatchQty(operation.getTransferBatchQty());
				// 加工批量
//				newOpTask.setProcessBatchQty(operation.getProcessBatchQty());
				// 批量工时
//				newOpTask.setProcessBatchRunTime(operation
//						.getProcessBatchRunTime());
				newOpTask.setTaskName(operation.getOperationName());
				newOpTask.setOperationId(operation.getOperationId().floatValue());
				newOpTask.setOperationIdDesc(operation.getOperationIdDesc());
//				if (operation.getEstiPostOpTime() != null)
//					newOpTask.setEstiPreTime(operation.getEstiPostOpTime());
//				if (operation.getEstiRunTime() != null)
//					newOpTask.setEstiRunTime(operation.getEstiRunTime());
//				if (operation.getEstiDelayTime() != null)
//					newOpTask.setEstiDelayTime(operation.getEstiDelayTime());

				newOpTask.setPartUid(partTask.getPartUid());
				newOpTask.setScheme(scheme);
				newOpTask.setTaskUid(IdentityGenerator.GetIdentityUUID());
				newOpTask.setOpUid(operation.getUuid());
				newOpTask.setBatchNum(partTask.getBatchNum());
				newOpTask.setPlanQty(partTask.getPlanQty());
				newOpTask.setTaskState(SOperationTask.TASKSTATE_READY);
				// newOpTask.setCompleteQty(toTask);
				// todo 完成数比较难于分配
				newOpTask.calTaskWork();
				// 工作中心，不用operation.getWorkCenter避免那些非法数据
				WorkCenter wc = this.workCenterDao.getById(operation
						.getWorkCenterUid());
				// Hibernate.initialize(wc);
				if (wc == null || wc.getWorkCenterUid() == null
						|| wc.getWorkCenterName() == null) {
					newOpTask.setDeviceClass("cooperationCenter");
					// 应该分成几类工作中心
					newOpTask.setDeviceClassName("外协中心");
					if (operation.getDeptUid() == null)
						newOpTask.setMasterShop("WX");
					else {
						newOpTask.setMasterShop(operation.getDeptUid());
					}

				} else {
					newOpTask.setDeviceClass(wc.getWorkCenterUid());
					newOpTask.setDeviceClassName(wc.getWorkCenterName());
					newOpTask.setMasterShop(wc.getDeptUid());
					// added by hba
					newOpTask.setMasterShopName(wc.getDept().getDeptName());

					// log.debug(newOpTask + "部门编号为:" +
					// newOpTask.getMasterShop()
					// + " 调度部门编号：" + scheme.getDeptUid());
					// if
					// (newOpTask.getMasterShop().indexOf(scheme.getDeptUid()) <
					// 0) {
					// newOpTask.setDeviceClass("cooperationCenter");
					// // 应该分成几类工作中心
					// newOpTask.setDeviceClassName("外协中心");
					// }
				}

				// newOpTask.setPredLinkSet(new HashSet<SOperationLink>());
				// newOpTask.setSuccLinkSet(new HashSet<SOperationLink>());
				newOpTask.setParentTask(partTask);

				// 先设置完后再计算可选资源
				// 或者将两者结合起来
				// todo
				// 应用工序约束后会自动调用计算可选资源的函数
				// todo
				// scheduleOperationTaskManager.calcAlterResourceList(newOpTask);

				// newOpTask
				// .setTaskScheduleType(newOpTask.TASKSCHEDULETYPE_COMBINEBATCH);

				// 恢复原来的状态
				if (oldStateMap.containsKey(newOpTask.getOperationIdDesc())) {
					SOperationTask oldStateTask = oldStateMap.get(newOpTask
							.getOperationIdDesc());
					newOpTask.setTaskState(oldStateTask.getTaskState());
					newOpTask.setCompleteQty(oldStateTask.getCompleteQty());
					newOpTask.setDeviceUid(oldStateTask.getDeviceUid());
					newOpTask.setDevice(oldStateTask.getDevice());
					newOpTask.setPlanStart(oldStateTask.getPlanStart());
					newOpTask.setPlanFinish(oldStateTask.getPlanFinish());
					newOpTask.setLocked(oldStateTask.getLocked());
					newOpTask.setEarlyStart(oldStateTask.getEarlyStart());
					newOpTask.setLateFinish(oldStateTask.getLateFinish());
					// 应该也将实际开始和结束继承下来 by hba
					newOpTask.setActualFinish(oldStateTask.getActualFinish());
					newOpTask.setActualStart(oldStateTask.getActualStart());
					newOpTask.setManualScheduleState(oldStateTask
							.getManualScheduleState());
					// hba
				}

				scheme.getAllOperationTaskMap().put(newOpTask.getTaskUid(),
						newOpTask);

				// 直接添加到数据库中
				this.scheduleOperationTaskManager.add(newOpTask);

				// 将工序约束加进来
				// 并且让它刷新本工序的工时
				scheduleOperationTaskManager.refreshOperationDevice(scheme,
						operation.getUuid(), newOpTask);
				opTaskList.add(newOpTask);
			}

			// 添加缺省链接关系
			// lqm todo
			// 应该考虑网络
			for (int i = 1; i < opTaskList.size(); i++) {
				scheduleLinkManager.addLink(opTaskList.get(i - 1), opTaskList
						.get(i), 1, 0);
			}

			scheduleOperationTaskManager.calTaskDistance(partTask);

			if (partTask.getTaskScheduleState().equals(
					SPartTask.TASKSCHEDULESTATE_STARTED))
				this.scheduleOperationTaskManager.intoSchedule(opTaskList);

		}
		oldStateMap = null;

	}

	public RoutingManager getRoutingManager() {
		return routingManager;
	}

	public void setRoutingManager(RoutingManager routingManager) {
		this.routingManager = routingManager;
	}

	 
	public void refreshSlackAndColor(ScheduleScheme scheme,
			Collection<SPartTask> partTasks) throws Exception {
		// TODO Auto-generated method stub
		// by lqm
		// 重新计算松弛率
		for (SPartTask partTask : partTasks) {
			if (partTask.getLateFinish() != null) {
				partTask.setControlFinish(partTask.getLateFinish());
			} else
				partTask.setControlFinish(scheme.getScheduleFinish());
			this.calcSlack(partTask);
		}
		priorityCalc.calcPartTaskPriority(partTasks);
		// priorityCalc.calcPartTaskPriority(scheme.getCombineBatchList());
		// by lqm
	}

	public PriorityCalc getPriorityCalc() {
		return priorityCalc;
	}

	public void setPriorityCalc(PriorityCalc priorityCalc) {
		this.priorityCalc = priorityCalc;
	}

	 
	public void intoSchedule(List<SPartTask> partTaskList) throws Exception {
		if (partTaskList != null && partTaskList.size() > 0) {
			for (SPartTask sp : partTaskList) {
				intoSchedule(sp);
			}
		}
	}

	 
	public void intoSchedule(SPartTask partTask) throws Exception {
		// 如果已经在排产集中，则直接退出
		if (SPartTask.TASKSCHEDULESTATE_STARTED == partTask
				.getTaskScheduleState())
			return;

		partTask.setTaskScheduleState(SPartTask.TASKSCHEDULESTATE_STARTED);
		partTask.getScheme().getSchedulePartTasks().add(partTask);
		this.scheduleOperationTaskManager.intoSchedule(partTask
				.getOperationTaskList());

		this.update(partTask);
		// 为新的批次赋值颜色 hba
		partTask.getScheme().initColorMap();
		// List<SOperationTask> operationTaskList = partTask
		// .getOperationTaskList();
		// if (operationTaskList != null && operationTaskList.size() > 0) {
		// for (SOperationTask operationTask : operationTaskList) {
		// operationTask
		// .setTaskScheduleState(SOperationTask.TASKSCHEDULESTATE_STARTED);
		// }
		// }

	}

	 
	public void outSchedule(List<SPartTask> partTaskList, Boolean isWaiting)
			throws Exception {
		if (partTaskList != null && partTaskList.size() > 0) {
			for (SPartTask sp : partTaskList) {
				outSchedule(sp, isWaiting);
			}
		}

	}

	 
	public void outSchedule(SPartTask partTask, Boolean isWaiting)
			throws Exception {
		// 如果不是已经在排产集中，则直接退出
		if (SPartTask.TASKSCHEDULESTATE_STARTED != partTask
				.getTaskScheduleState())
			return;

		// // TODO Auto-generated method stub
		// // by zje
		// partTask.setPlanStart(null);
		// partTask.setPlanFinish(null);
		// List<SOperationTask> operationTaskList = partTask
		// .getOperationTaskList();
		//
		// if (operationTaskList != null && operationTaskList.size() > 0) {
		// for (SOperationTask operationTask : operationTaskList) {
		// operationTask.setDeviceUid(null);
		// operationTask.setDevice(null);
		// operationTask.setPlanStart(null);
		// operationTask.setPlanFinish(null);
		// operationTask.setLocked(0);
		// operationTask
		// .setTaskScheduleState(SOperationTask.TASKSCHEDULESTATE_WAITING);
		// if (operationTask.getGroupTask() != null) {
		// this.scheduleOperationTaskManager.deleteMemberTask(
		// operationTask.getGroupTask(), operationTask);
		// }
		//
		// }
		// }

		// 进行移除任务的有效性判断，如果有工序任务正在运行中，则不允许移除

		// for (SOperationTask so : partTask.getOperationTaskList()) {
		// if (so.isRunning()) {
		// String strErr = "该零组件任务有工序处于下发状态，不能从排产集合中移除！\n 工序为:"
		// + so.toFriendlyString();
		// if (so.getDevice() != null)
		// strErr += ",设备为：" + so.getDevice().getDeviceName();
		// throw new Exception(strErr);
		// }
		// }

		if (isWaiting == null || isWaiting.equals(true))
			partTask.setTaskScheduleState(SPartTask.TASKSCHEDULESTATE_WAITING);
		else
			partTask.setTaskScheduleState(SPartTask.TASKSCHEDULESTATE_NO);

		partTask.setPlanStart(null);
		partTask.setPlanFinish(null);

		partTask.getScheme().getSchedulePartTasks().remove(partTask);
		this.scheduleOperationTaskManager.outSchedule(partTask
				.getOperationTaskList(), isWaiting);

		this.update(partTask);
		// 为新的批次赋值颜色 hba
		partTask.getScheme().initColorMap();
		// lqm todo

		DemandSTaskLinkManager demandSTaskLinkManager = SpringUtils
				.getBean("demandSTaskLinkManager");

		demandSTaskLinkManager.deleteLinksByTaskUid(partTask.getScheduleUid(),
				partTask.getTaskUid());

	}

	 
	public void refreshTaskDistance(SPartTask partTask) throws Exception {
		List<SOperationTask> operationTaskList = partTask
				.getOperationTaskList();

		int size = operationTaskList.size();
		int iDistance = 0;
		int iSize = operationTaskList.size();
		for (int j = 0; j < iSize; j++) {
			SOperationTask operationTask = operationTaskList.get(j);
			log.debug("开始刷新工序距离：" + operationTask);
			// 如果已经完成
			if (operationTask.isFinished()) {
				iDistance = 0;
				continue;
			}
			operationTask.setTaskDistance(iDistance++);

		}

	}

	public OperationDao getOperationDao() {
		return operationDao;
	}

	public void setOperationDao(OperationDao operationDao) {
		this.operationDao = operationDao;
	}

	public OperationManager getOperationManager() {
		return operationManager;
	}

	public void setOperationManager(OperationManager operationManager) {
		this.operationManager = operationManager;
	}

	public SPartTaskDao getSchedulePartTaskDao() {
		return schedulePartTaskDao;
	}

	public void setSchedulePartTaskDao(SPartTaskDao schedulePartTaskDao) {
		this.schedulePartTaskDao = schedulePartTaskDao;
		this.basicDao = schedulePartTaskDao;
	}

	public PartTaskDao getPartTaskDao() {
		return partTaskDao;
	}

	public void setPartTaskDao(PartTaskDao partTaskDao) {
		this.partTaskDao = partTaskDao;
	}

	public PartTaskManager getPartTaskManager() {
		return partTaskManager;
	}

	public void setPartTaskManager(PartTaskManager partTaskManager) {
		this.partTaskManager = partTaskManager;
	}

	@Transactional
	 
	public void syncLateFinish(ScheduleScheme scheme) throws Exception {
		for (SPartTask partTask : scheme.getAllPartTaskMap().values()) {
			partTask.setLateFinish(null);
		}

		for (SPartTask partTask : scheme.getAllPartTaskMap().values()) {
			if (log.isDebugEnabled()) {
				if (partTask.getTaskUid().equals("3681368")) {
					log.debug(partTask);
				}
			}
			if (partTask.getTaskScheduleType().equals(
					SPartTask.TASKSCHEDULETYPE_NORMAL)) {

				PartTask oPartTask = this.getOPartTask(partTask);
				if (oPartTask != null && oPartTask.getLateFinish() != null) {
					partTask.setIsCritical(oPartTask.getIsCritical().intValue());
					partTask.setLateFinish(oPartTask.getLateFinish());
				}
			}
		}

		for (SPartTask partTask : scheme.getAllPartTaskMap().values()) {
			if (partTask.getTaskScheduleType().equals(
					SPartTask.TASKSCHEDULETYPE_COMBINEBATCH)) {
				List<SPartTask> subTaskList = partTask.getCombinedBatchs();
				if (subTaskList != null && subTaskList.size() > 0) {
					Date minDate = null;
					int maxCriticalLevel = 0;
					for (SPartTask childPartTask : partTask.getCombinedBatchs()) {
						if (childPartTask.getLateFinish() != null
								&& (minDate == null || minDate
										.after(childPartTask.getLateFinish())))
							minDate = childPartTask.getLateFinish();

						if (childPartTask.getIsCritical() != null
								&& childPartTask.getIsCritical() > maxCriticalLevel)
							maxCriticalLevel = childPartTask.getIsCritical();
					}

					partTask.setIsCritical(maxCriticalLevel);

					if (minDate != null)
						partTask.setLateFinish(minDate);
				}
			}
		}

		this.update(scheme.getAllPartTaskMap().values());

	}

	@Transactional(propagation = Propagation.NOT_SUPPORTED)
	 
	public void resetScheduleCol(ScheduleScheme scheme) throws Exception {
		// 不需要调度的零件任务集合，主要是对taskschedulestate=-1这个状态还不信任
		Set<SPartTask> notSchedulePartTaskSet = new HashSet<SPartTask>();
		for (SPartTask partTask : scheme.getAllPartTaskMap().values()) {
			if (partTask.getTaskScheduleType().equals(
					SPartTask.TASKSCHEDULETYPE_COMBINEBATCH)) {
				List<SPartTask> combineBatchList = partTask.getCombinedBatchs();
				if (combineBatchList != null && combineBatchList.size() > 0) {
					for (SPartTask sp : combineBatchList) {
						notSchedulePartTaskSet.add(sp);
					}
				}

			}
		}
		for (SPartTask partTask : scheme.getAllPartTaskMap().values()) {
			if (log.isDebugEnabled()) {
				if (partTask.getTaskUid().equals("3681368")) {
					log.debug(partTask);
				}
			}

			// if (partTask.getLateFinish() != null
			// && partTask.getTaskScheduleState().equals(
			// SPartTask.TASKSCHEDULESTATE_WAITING))
			// this.intoSchedule(partTask);

			// if (partTask.getLateFinish() == null
			// && partTask.getTaskScheduleState().equals(
			// SPartTask.TASKSCHEDULESTATE_STARTED))
			// {
			// try {
			// this.outSchedule(partTask, true);
			// } catch (Exception e) {
			// // TODO Auto-generated catch block
			// log.warn(e.getMessage());
			//
			// }
			// }
			try {
				if (notSchedulePartTaskSet.contains(partTask)) {// 直接踢出调度
					this.outSchedule(partTask, false);
				} else {
					if (partTask.getLateFinish() != null)
						this.intoSchedule(partTask);
					else {
						this.outSchedule(partTask, true);
					}
				}

			} catch (Exception e) {
				// TODO Auto-generated catch block
				log.warn(e.getMessage());
			}

		}

		notSchedulePartTaskSet = null;
	}

	@Transactional
	 
	public void outSchedule(SPartTask outPartTask) throws Exception {
		ScheduleScheme scheme = outPartTask.getScheme();
		// 不需要调度的零件任务集合，主要是对taskschedulestate=-1这个状态还不信任
		boolean isWaiting = true;

		for (SPartTask partTask : scheme.getAllPartTaskMap().values()) {
			if (partTask.getPartUid().equals(outPartTask.getPartUid())
					&& partTask.getTaskScheduleType().equals(
							SPartTask.TASKSCHEDULETYPE_COMBINEBATCH)) {
				List<SPartTask> combineBatchList = partTask.getCombinedBatchs();
				if (combineBatchList != null && combineBatchList.size() > 0) {
					if (combineBatchList.contains(outPartTask))// 包含则不需要调度
						isWaiting = false;
				}

			}
		}

		this.outSchedule(outPartTask, isWaiting);

	}

	 
	public void init(ScheduleScheme scheme, SPartTask partTask) {
		if (partTask.isInitialized())
			return;
		List<SOperationTask> operationTaskList = partTask
				.getOperationTaskList();
		if (operationTaskList.size() == 0) {
			// deletePartTaskUidList.add(partTask.getTaskUid());
			return;
		}
		log.debug("开始初始化零组件任务：" + partTask);
		/**
		 * 按照工序号排序
		 */
		partTask.sortByOperationId();
		// partTask
		// .setCurrentOperation(partTask.getOperationTaskList().get(0));
		if (partTask.getControlFinish() == null) {
			partTask.setControlFinish(scheme.getScheduleFinish());
		}

		/**
		 * 将最后一道工序任务最后一道工序的交货期与零件任务交货期保持一致
		 */
		int size = operationTaskList.size();
		operationTaskList.get(size - 1).setControlFinish(
				partTask.getControlFinish());

		/**
		 * 将首道工序任务最早开始时间与零件任务最早开始保持一致
		 */
		if (partTask.getLateFinish() != null)
			operationTaskList.get(size - 1).setLateFinish(
					partTask.getLateFinish());
		if (partTask.getEarlyStart() != null)
			operationTaskList.get(0).setEarlyStart(partTask.getEarlyStart());

		int iDistance = 0;
		int iSize = operationTaskList.size();

		/**
		 * 初始化工序距离与补齐链接关系
		 */
		for (int j = 0; j < iSize; j++) {
			SOperationTask operationTask = operationTaskList.get(j);
			log.debug("开始初始化工序任务：" + operationTask);
			// 如果已经完成
			if (operationTask.isFinished()) {
				iDistance = 0;
				continue;
			}
			operationTask.setTaskDistance(iDistance++);

			// 补充遗失链接
			// 最应该移除的代码

			if ((j < iSize - 1)
					&& (operationTask.getSuccLinkSet() == null || operationTask
							.getSuccLinkSet().size() == 0)) {
				try {
					// 非开始任务
					if (!operationTaskList.get(j + 1).isStarted()) {
						scheduleLinkManager.addLink(operationTask,
								operationTaskList.get(j + 1),
								SOperationLink.LINKTYPE_FTS, 0);
					}
				} catch (Exception e) {
					log.error(e);
				}
			}

			// this.scheduleOperationTaskManager.init(scheme, operationTask);
		}

		// 刷新剩余工时，用作整个零件越快越好的排序
		// 应该将这个函数孤立出来，用于修改工时时刷新整个零件任务的工时
		// lqm todo
		// 也要考虑整个几道工序过来加工的协作任务情况
		double remainWork = 0d;
		for (int j = iSize - 1; j >= 0; j--) {
			SOperationTask operationTask = operationTaskList.get(j);
			remainWork += operationTask.getEstiTaskWork();
			operationTask.setRemainWork(remainWork);
		}

		// // 先初始化完再计算松弛率
		// schedulePartTaskManager.calcSlack(partTask);
		// for (SOperationTask operationTask :
		// partTask.getOperationTaskList()) {
		// operationTask.setSlackFactor(partTask.getSlackFactor());
		// }

		partTask.setInitialized(true);

	}

	 
	public String getCurrentOperationIdDesc(ScheduleScheme scheme,
			SPartTask partTask) {

		String currentOperationIdDesc = null;

		if (partTask != null && partTask.getCurrentOperation() != null)
			currentOperationIdDesc = partTask.getCurrentOperation()
					.getOperationIdDesc();

		String taskUid = null;
		try {
			if (partTask.getTaskScheduleType() == SPartTask.TASKSCHEDULETYPE_NORMAL)
				taskUid = partTask.getTaskUid();
			else if (partTask.getTaskScheduleType() == SPartTask.TASKSCHEDULETYPE_COMBINEBATCH) {
				if (partTask.getCombinedBatchs().size() > 0)// 任取一个子任务的当前工序
					taskUid = partTask.getCombinedBatchs().get(0).getTaskUid();
			}

			PartTask opartTask = (PartTask) this.partTaskDao.getById(taskUid);
			// if (opartTask == null) {
			// log.debug("");
			//
			// }
			if (opartTask != null) {
				if (opartTask.getCurrentOperationTask() != null)
					currentOperationIdDesc = opartTask
							.getCurrentOperationTask().getOperationIdDesc();
			}

		} catch (Exception e) {
			// TODO Auto-generated catch block
			log.error(e);
		}

		return currentOperationIdDesc;
	}

	 
	public SPartTask getSchedulePartTask(String scheduleUid, String partTaskUid) {
		ScheduleScheme scheme = ScheduleUtils.getScheduleScheme(scheduleUid);

		if (scheme.getAllPartTaskMap().containsKey(partTaskUid))
			return scheme.getAllPartTaskMap().get(partTaskUid);

		return null;
	}

	 
	public SPartTask getSchedulePartTask(ScheduleScheme scheme,
			PartTask originPartTask) {

		if (scheme.getAllPartTaskMap().containsKey(originPartTask.getTaskUid())) {
			return scheme.getAllPartTaskMap().get(originPartTask.getTaskUid());

		} else {
			return getSchedulePartTask(scheme, originPartTask.getPartUid(),
					originPartTask.getBatchNum());
		}

		// return null;
	}

	public SPartTask getSchedulePartTask(ScheduleScheme scheme, String partUid,
			String batchNum) {

		for (SPartTask p : scheme.getAllPartTaskMap().values()) {
			if (p.getPartUid().equals(partUid)
					&& p.getBatchNum().equals(batchNum))
				return p;

		}

		return null;
	}

	@Transactional
	 
	public void changePartTaskQty(ScheduleScheme scheme, SPartTask partTask,
			Double newPlanQty) throws Exception {
		try {
			partTask.setPlanQty(newPlanQty);
			this.update(partTask);

			// 让工序任务与零件任务数量相同
			for (SOperationTask so : partTask.getOperationTaskList())
				so.setPlanQty(newPlanQty);

			this.scheduleOperationTaskManager.update(partTask
					.getOperationTaskList());

		} catch (BaseBusinessException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

	}

	// @Transactional
	 
	public void clearLateFinish(ScheduleScheme scheme) throws Exception {
		for (SPartTask partTask : scheme.getAllPartTaskMap().values()) {
			partTask.setLateFinish(null);
		}
		this.update(scheme.getAllPartTaskMap().values());

		List<PartTask> partTaskList = this.partTaskDao
				.getWipPartTasksByDept(scheme.getDeptUid());
		if (partTaskList != null && partTaskList.size() > 0) {
			for (PartTask partTask : partTaskList) {
				partTask.setLateFinish(null);
			}
			this.partTaskManager.update(partTaskList);
		}

	}

	//
	// /**
	// * 临时用于导入在制品数据
	// *
	// * @param currentOperationIdDesc
	// * @return
	// */
	// private String getTmpOperationIddesc(String currentOperationIdDesc) {
	// for (int i = 0; i < currentOperationIdDesc.length(); i++) {
	// if (!currentOperationIdDesc.substring(i, i + 1).equals("0")) {
	// return currentOperationIdDesc.substring(i,
	// currentOperationIdDesc.length());
	// }
	// }
	// return null;
	// }

	 
	public void importFromWip(SPartTask sp, String currentOperationIddesc)
			throws Exception {
		if (sp.getOperationTaskList().size() == 0) {

			ScheduleScheme scheme = sp.getScheme();
			Routing planRouting = scheduleRoutingManager.getDefaultRouting(sp
					.getPartUid());
			if (planRouting != null) {
				// String currentOperationIdDesc = null;
				// // 按照新方式分解产生数据
				// if (currentOperationIddesc != null) {
				//
				// for (Operation operation : planRouting.getOperations()) {
				// if
				// (operation.getOperationIdDesc().equals(currentOperationIdDesc))
				// {
				// currentOperationIdDesc = operation
				// .getOperationIdDesc();
				// break;
				// }
				//
				// }
				//
				// }
				this.applyRouting(scheme, sp, planRouting,
						currentOperationIddesc);
				this.init(scheme, sp);

			}
		}

	}


	@Override
	public List<SOperationTask> getOpTaskListForShiftProduction(ScheduleScheme scheme, SPartTask partTask)
			throws Exception {
		// TODO Auto-generated method stub
		return null;
	}

	 


}